Thank you * 1,000,000 tokumaru!!! Being able to see just how it should work meant volumes for me because... I have received help from other threads... I think that's where I got the function linear_position from... and I also had another function called use_colTables that I got from Kasumi... and somehow I mixed them both together so our girl would fall and reach the ground and stop!! And then after fixing some things she began to fall through the ground... and I messed up and couldn't remember how the two functions worked together... until just a little while ago I read your code there and I went and changed use_colTables and linear_position16bit a little and IT WORKS!!!!!!!!!!!!!!!!!!!!!!!!!!!! I'M SO HAPPY THANK YOU SO MUCH TOKUMARU!! It was so nice to finally get some code that encompassed the entire method for linear position! WOOOOOHOOOOOO!!tokumaru wrote:Looks correct to me. Take care with that optimization you did though: you might look at (Y / 16) * 16 and feel tempted to skip all the shifting, but then you'll be keeping the lower 4 bits of Y, which will screw up the result when you add (X / 16) later. The correct way to optimize this formula is (Y AND $F0) * 2 + (X / 16). Multiplications and divisions are obviously done by shifting bits.unregistered wrote:Is that correct?Code: Select all
;= ... (Y / 16) * (2 * 16) + (X / 16) ;= ... ((Y / 16) * 16) * 2 + (X / 16)
Also, since you have only 2 screens worth of collision data, you should ignore the higher bits (you only need bits 0 through 8) of the X coordinate, otherwise you might end up with a pointer to a memory location past the area you have defined for collision data.
If you add $600 to the result from the formula above, you'll end up with a 16-bit pointer you can use to read from this table. You could even skip adding (X / 16) to the pointer and put that into the Y registers instead. The complete code might look like this:unregistered wrote:My collision data is kept in a 15 rows by 32 columns table in 0600-07DF.
This is just one way to do it. Another approach would be to store the collision data a bit differently, as 2 16x15 blocks, instead of a single 32x15 one. That way you could use only the lower bytes of the coordinates to form an 8-bit index and check the 9th bit of the X coordinate to decide between reading from the first or the second collision table. The options are endless, so pick what works best for you. =)Code: Select all
lda PixelY ;8-bit Y coordinate and #$0f ;same as shifting right 4 times and then left 4 times asl ;shift one more time to complete the multiplication by 32 sta Pointer+0 ;the low byte of the pointer is ready lda #$06 ;prepare to add the high byte of the base address adc #$00 ;add to the highest bit (carry) of PixelY * 32 sta Pointer+1 ;the high byte of the pointer is ready lda PixelX+1 ;high byte of 16-bit X coordinate lsr ;get the only bit we need from it lda PixelX+0 ;low byte of the 16-bit X coordinate ror ;put the high bit in lsr ;shift 3 times to complete the division by 16 lsr lsr tay ;put the row offset in the index register lda (Pointer), y ;get the collision data
edit:
this is part of my edit... wow, it would be fun to try this Mario's way (thank U tepples )... but it works so far with the 32x15 way that my code does... and I do think that it would be nice to access with an 8 bit index AND also it would be easier to read the two 16x15 halves ( 16x15 instead of 16x13 because my game doesn't use a status bar unlike Mario who does) instead of the 32x15 thing that I have because the hex editor in FCEUX lists everything in 16 sections... the extra lines will be confusing... but I'm going to create a Monitor coveringtokumaru wrote:This might be a good approach because it better matches the name table layout, in addition to the possibility of accessing any part of each table with an 8-bit index.tepples wrote:This is what Super Mario Bros. does: a 32x13-metatile sliding window stored as two 16x13 halves.
final edit.