This page is a mirror of Tepples' nesdev forum mirror (URL TBD).
Last updated on Oct-18-2019 Download

16 bit arithmetic in 6502 (and jump logic)!

16 bit arithmetic in 6502 (and jump logic)!
by on (#55816)
In a few topics I have seen the use of 16 bit numbers(i.e. coordinates) for smooth moving/jumping of the sprite.

All the arithmatic in 6502 is 8 bit. How a 16 bit calculation can be done?

For example in case of a vertical jump of the character: My first guess is that we have 2 consecutive bytes, one for keeping the integer part and one for keeping the fractional part of the Y coordinate and the arithmatic is performed separately on each of these parts.

Any suggestions about "jumping of sprite character" will be appreciated.

by on (#55817)
Yes, you have two bytes (you can use more of course but 16 bits should be enough for most cases), the bytes don't have to be consecutive. Then simply perform 16 bit addition and subtraction on those numbers, you can see how to do it here: http://www.obelisk.demon.co.uk/6502/algorithms.html

by on (#55825)
Your guess is right - but I rather like to have upper 8 bits indicate metatile position (so the lower 8 bits are 4 bits for pixels and 4 bit for fraction of pixels).
That way you can make map large up to 256*256 meta-tiles, and 16th of pixels is LARGELY fine enough for whathever you'd want to.

by on (#55827)
Bregalad wrote:
Your guess is right - but I rather like to have upper 8 bits indicate metatile position

Of course it breaks down with maps wider than 256 metatiles, as seen in many sidescrollers. For instance, Super Mario World maps are 512 by 32 MT.

by on (#55830)
16 bit addition
Code:
;initialization
  lda #$00
  sta byte0;Low Byte
  sta byte1;High Byte

;Iteration One
  clc;Cleared only before the first addition in 16bit addition
  lda byte0;a = #$00
  adc #$80;a = #$80, carry clear
  sta byte0;byte0 = #$80
 
  lda byte1
  adc #$00;I'm adding zero, but if the carry was set, I'd be adding one
  sta byte1;byte1 = #$00
;Iteration Two
  clc;Cleared only before the first addition in 16bit addition
  lda byte0;a = #$80
  adc #$80;#$80 + #$80 = #$0100 but that won't fit in a byte.
  ;So we get #$00, but the carry is set because the result would have been greater than #$FF
  sta byte0;byte0 = #$00

  lda byte1
  adc #$00;adc adds the number you give it plus the carry bit.
;It's set because the result of the last addition would have been greater than #$FF. So I'm adding #$00 plus 1 thanks to the set carry.
  sta byte1;byte1 = #$01
;End Result
;256 * High Byte (byte1 in this case) + Low Byte (byte0) gives you your 16bit result.

;byte0 = #$00
;byte1 = #$01

;256 * 1 + 0 = 256.

;Or... like it's explained in the comments #$(High Byte)(Low Byte)

;#$0100 = 256.


One last note, is you need not always add #$00 in 16bit addition, it's just easiest to show how the carry flag works that way (since one might assume adding zero would not change the accumulator). By first adding #$80 to the low byte, then adding #$00 to the high byte I really added #$0080 to the 16bit number stored. But I could just as easily add #$FE40, by first adding #$40 to the low byte, then adding #$FE to the high byte.

Hmm... on to your jumping question. 16bit addition can help you, but as Bregalad stated, a whole byte is a lot to dedicate to the fractional part of a pixel. Either way, for a jump you,

1. Set y velocity when the jump is triggered.
;Then loop the following each frame
2. Add 1 (or more depending on your gravity) to the velocity value.
3. Add y velocity to position

If you did use a whole byte for fractions of a pixel, you'd use the high byte to display where the sprite is on screen (the whole pixel) and the low byte would keep fractions of a pixel. Though for scrolling you'd of course need an additional byte.

by on (#55839)
Like it's been said, depending on the dimensions of your levels you need more than 8 bits for the whole part of the coordinates. The only case where 8 bits will be fine is when the whole action happens on a single screen, but even then you wouldn't be able to jump past the top of the screen or something like that, so choose the precision of your coordinates carefully.

by on (#55863)
Even though it's quite old, you can check out my Solar Wars source code and diary -- I went through these things for the first time then (too) -- figuring out how many bytes to use for position/velocity, etc, and how to handle acceleration.

You might find it useful.