Jess Ragan Posted July 3 Share Posted July 3 This is tricky, since sprite locations and character data locations don't match up perfectly, but I think I've figured it out. IF VPEEK (6144 + (spritex / 8) + ((spritey / 8) * 32)) = 205 THEN code END IF I've divided spritex by eight, and then divided spritey by eight and then multiplied the answer by 32, to find what data is directly beneath the sprite. This is very handy for maze games, like the one I was planning to make! Probably wouldn't hurt for pathfinding, either. 1 Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/ Share on other sites More sharing options...
artrag Posted July 3 Share Posted July 3 (edited) In the formula try this expression instead of dividing by 8 and multiply by 32. (Spritey and $F8)*4 The resulting asm should be faster and shorter Edited July 3 by artrag Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5494986 Share on other sites More sharing options...
Jess Ragan Posted July 4 Author Share Posted July 4 All right. I've noticed that your code is dependent on Boolean operands, which probably is more efficient but also leaves me struggling to understand it. How does this work? Does the AND statement work the way a logic gate would on a motherboard? In other words, two bits are compared, and the result is 0 if they're different, but 1 if they're both the same? I kind of understand the basic concept, but I don't understand how that knowledge could be practically applied in a program. Where would this bit math be useful? Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5495489 Share on other sites More sharing options...
+nanochess Posted July 4 Share Posted July 4 1 hour ago, Jess Ragan said: All right. I've noticed that your code is dependent on Boolean operands, which probably is more efficient but also leaves me struggling to understand it. How does this work? Does the AND statement work the way a logic gate would on a motherboard? In other words, two bits are compared, and the result is 0 if they're different, but 1 if they're both the same? I kind of understand the basic concept, but I don't understand how that knowledge could be practically applied in a program. Where would this bit math be useful? When working in 8-bit variables you can do these for example: Y = Y AND $FE ' Removes least-significant bit. Equivalent to divide by 2, and multiply by 2. Y = Y AND $FC ' Removes 2 least-significant bits. Equivalent to divide by 4, and multiply by 4. Y = Y AND $F8 ' Removes 3 least-significant bits. Equivalent to divide by 8, and multiply by 8. So ARTRAG's code helps you to avoid a hefty division operation, and your code will be faster. In special if you use the routine in several places. #c = (Y AND $F8) * 4 ' Removes 3 least-significant bits. Equivalent to divide by 8, and multiply by 8, after further multiplying it by 4 (8*4=32), it is the row character of your sprite. 1 Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5495519 Share on other sites More sharing options...
artrag Posted July 4 Share Posted July 4 Jess, note that 0 and 0 = 0 For the rest, it is as you said 1 and 0 = 0 0 and 1 = 0 1 and 1 = 1 Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5495689 Share on other sites More sharing options...
artrag Posted July 4 Share Posted July 4 (edited) Another case where binary logic is useful could be when you want to test a number of variables to see if any of them is eg bigger than a number power of 2. Assume you need to test if any among #X,#Y,#Z - unsigned words- is bigger then or equal to eg 256 This expression (#X or #Y or #Z) and $FF00 will be non zero if any of them is equal or larger than 256 Edited July 4 by artrag 1 Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5495713 Share on other sites More sharing options...
Jess Ragan Posted July 7 Author Share Posted July 7 Wait, it divides by eight, then multiplies by eight? What's the point of that? That would just return you to the number you had before you processed it. Or did you mean that AND multiplies while OR divides? Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5496963 Share on other sites More sharing options...
artrag Posted July 7 Share Posted July 7 (edited) You need to get rid of the lower 3 bits of your variable. When you divide by 2 you shift right the binary representation of the number of one bit. As your variable is integer, the bits representing the fractional part are lost. Look at your original formula (spritey / 8 ) * 32 You divide by 8 before multiplying by 32 because you need to remove the last 3 bits. Should you invert the operations you would get the correct result (spritey / 8) * 32 != spritey * 32 /8 Edited July 7 by artrag Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497003 Share on other sites More sharing options...
artrag Posted July 7 Share Posted July 7 (edited) https://www.rapidtables.com/convert/number/decimal-to-binary.html?x=255 Maybe you can find useful a bit of math background https://ryanstutorials.net/binary-tutorial/binary-conversions.php Edited July 7 by artrag Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497004 Share on other sites More sharing options...
+nanochess Posted July 7 Share Posted July 7 7 hours ago, Jess Ragan said: Wait, it divides by eight, then multiplies by eight? What's the point of that? That would just return you to the number you had before you processed it. Or did you mean that AND multiplies while OR divides? For getting the screen row on the VRAM memory we need to multiply the row by 32. But you don't have a row, you have a pixel coordinate. So you need to divide that pixel coordinate by 8 to get the row. Instead of dividing by 8, we simply clear the lower 3 bits using AND $F8. Now it is a row number multiplied by 8. We only need to multiply by 4 (8*4 = 32) to get the same effect as x/8*32. For example, your pixel y-coordinate is 93, and you want to get the byte for the row in the VRAM in this way 93 / 8 * 32 = final result. 93 in binary is 01011101 The standard method is 93 / 8 * 32. 93 / 8 = 11, binary is 00001011 Technically we could have seen the division as shifting to the right bit by bit. 01011101 = 93 00101110 = one bit shift to the right. 00010111 = one bit shift to the right. 00001011 = one bit shift to the right, 11 However, CVBasic currently isn't so smart to do it as shifting bit by bit, so it does a full division subroutine for this. Now, it multiplies it by 32, CVBasic is smart enough to implement it as shifting to the left bit by bit using ADD HL,HL. 00010110 = x2 00101100 = x4 01011000 = x8 multiplication 10110000 = x16 101100000 = x32 Notice how in all this mumble-jumble the basic bit pattern for eleven is preserved (1011). Now it becomes logical the AND $f8 operator for optimization, doing this (93 AND $F8) * 4 = final result. 01011101 = $5D = 93 11111000 = $F8 = 248 -------- = AND operation 01011000 = The row already multipled by x8 !!! (the value is the same as in the above x8 multiplication) So you need only to multiply by 4 to get the same value. 10110000 = x2 101100000 = x4 And this way you saved a very heavy division subroutine and speed up the multiplication pass. Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497069 Share on other sites More sharing options...
Jess Ragan Posted July 7 Author Share Posted July 7 (edited) Okay, so just to be absolutely sure... IF VPEEK (6144 + (shotx AND $F8) + (shoty AND $F8) * 4) = 127 THEN code END IF This would yield the results I'm looking for, right? Whatever is directly behind the bullet will be read, and if the character is 127, the code will be executed. shotx AND $F8 would be division by eight, and (shoty AND $F8) * 4 would be division by eight, multiplied by thirty two? Edited July 8 by Jess Ragan Missed a parenthesis! Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497359 Share on other sites More sharing options...
Jess Ragan Posted July 8 Author Share Posted July 8 This video is helping me understand how bitshifting works. It's an odd concept, but I could see how it could be useful. Also, if you put the value of the least significant bit in the position of the most significant bit after you bitshift, it works a bit like scrolling, which explains why ArtRag used Boolean math in his scrolling examples. Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497385 Share on other sites More sharing options...
Jess Ragan Posted July 8 Author Share Posted July 8 Still not totally getting this, I'm afraid. Using AND doesn't shift the bits over in this example; it merely removes them. bitsy = 255 CLS PRINT AT 0, "A variable that is ", bitsy PRINT AT 64, "Becomes ", bitsy AND $FE, " bitshifted by 2" PRINT AT 128, "Becomes ", bitsy AND $FC, " bitshifted by 4" PRINT AT 192, "Becomes ", bitsy AND $F8, " bitshifted by 8" PRINT AT 256, "Becomes ", (bitsy AND $F8) * 4, " with ArtRags formula" ' This just seems to remove bits, not shift the remainder over. What gives? ' Also, it's 992 with ArtRag's formula, which makes absolutely no sense WHILE 1 WEND The output is 254, 252, and 248, with 992 (!?) for the final formula. So it's doing something, but not the division I wanted. Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497397 Share on other sites More sharing options...
Jess Ragan Posted July 8 Author Share Posted July 8 (edited) Doing more research on this. You can shift a byte by one bit by either multiplying by 2 (the remaining bits move left), or dividing by 2 (the remaining bits move right). ArtRag's formula works in the game, but I'm still not sure how to divide shotx by eight without actually dividing shotx by eight. Edited July 8 by Jess Ragan Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497487 Share on other sites More sharing options...
artrag Posted July 8 Share Posted July 8 Leave shotx/8 you really need to divide by 8 for the x For the y divide and multiply so the and trick Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497501 Share on other sites More sharing options...
+nanochess Posted July 8 Share Posted July 8 The formula doesn't apply to the X-coordinate, only to the Y-coordinate. The X-coordinate still needs to be divided between 8: #c = 6144 + ((y AND $F8) * 4) + (x / 8 ) Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497531 Share on other sites More sharing options...
Jess Ragan Posted July 8 Author Share Posted July 8 Oh. Okay, see, I didn't know that. I figured there was some Boolean or Modulo or electronics math trick to make execution faster. What I decided to do was use ArtRag's code, but assign the answers to two variables to have them handy as references for the rest of the loop. I mean, yeah, it's more variables and more bytes out of the RAM, but I think I've got enough room to spare. It's like 812 bytes in total... it'd take some real work to run out of variables in a scenario like that. 1 Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5497532 Share on other sites More sharing options...
Lillapojkenpåön Posted October 9 Share Posted October 9 On 7/3/2024 at 5:23 AM, Jess Ragan said: This is tricky, since sprite locations and character data locations don't match up perfectly, but I think I've figured it out. IF VPEEK (6144 + (spritex / 8) + ((spritey / 8) * 32)) = 205 THEN code END IF I've divided spritex by eight, and then divided spritey by eight and then multiplied the answer by 32, to find what data is directly beneath the sprite. This is very handy for maze games, like the one I was planning to make! Probably wouldn't hurt for pathfinding, either. What is 205 a reference to? I thought it was the character number at that location but that doesn't seem to be it? Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5546555 Share on other sites More sharing options...
Kiwi Posted October 9 Share Posted October 9 11 minutes ago, Lillapojkenpåön said: What is 205 a reference to? I thought it was the character number at that location but that doesn't seem to be it? I called that Tile ID number. It's what picture it is pulling from out of 256 to print a 8x8 picture on the screen. Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5546564 Share on other sites More sharing options...
Lillapojkenpåön Posted October 9 Share Posted October 9 (edited) 21 minutes ago, Kiwi said: I called that Tile ID number. It's what picture it is pulling from out of 256 to print a 8x8 picture on the screen. I don't get it? At first I only had two characters, empty (0) and solid (1) checking if vpeek returned 1 worked fine, but now I have more characters, and checking for 1 also gives collision results for other characters, maybe it's because I'm using "or"? IF cont1.down THEN player_y = player_y + 5 #tile1 = VPEEK (6144 + left + (bellow * 32)) #tile2 = VPEEK (6144 + right + (bellow * 32)) IF #tile1 or #tile2 = 1 THEN player_y = player_y - overlapDown END IF END IF EDIT: I see it.. If #tile1 = 1 🤦♂️ Edited October 9 by Lillapojkenpåön Quote Link to comment https://forums.atariage.com/topic/368765-accurately-reading-character-data-behind-sprites/#findComment-5546568 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.