Calculating negative of 3 byte constants

Are you new to 6502, NES, or even programming in general? Post any of your questions here. Remember - the only dumb question is the question that remains unasked.

Moderator: Moderators

Post Reply
Siev
Posts: 4
Joined: Sun Apr 25, 2021 10:55 pm

Calculating negative of 3 byte constants

Post by Siev »

I am working on a physics system for my game which uses 3 bytes of precision. First byte showing your x or y pixel position on the screen. The physics constants are also defined like this:

GRAVITY0 = $0
GRAVITY1 = $20
GRAVITY2 = $1
MAX_FALL0 = $1
MAX_FALL1 = $10
MAX_FALL2 = $10
WALK_ACCEL0 = $0
WALK_ACCEL1 = $16
WALK_ACCEL2 = $80

And I'm also using 2's compliment for my negatives. This is how I calculate the negative of a 3 byte number:

clc
lda ax2
eor #$ff
adc #1
sta ax2
lda ax1
eor #$ff
adc #0
sta ax1
lda ax0
eor #$ff
adc #0
sta ax0

ax0 being the most significant and ax2 the least significant byte. But for values that are constant, calculating the negatives in real time doesn't make much sense since the value is always going to be the same and the addressing mode is always immediate. But this wouldn't work:

lda #-WALK_ACCEL0
sta ax0
lda #-WALK_ACCEL1
sta ax1
lda #-WALK_ACCEL2
sta ax2

since it's only calculating the negative of each byte by itself. The only other way that I can think is to also define the negatives as constants and use those when the negative of a constant is needed. But that would be very tedious to do as every time I want to change a number I also have to change its negative value. This feels like something that the assembler should be able to do automatically but I can't figure out how to do it in ca65. Thanks in advance.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: Calculating negative of 3 byte constants

Post by tokumaru »

Wow, 3 bytes is a lot for velocity and acceleration! In most games games, objects are restricted to moving 16 pixels at a time, because that's how big metatiles usually are and any movement bigger than that would cause them to go through solid blocks... So 1 byte for the whole part and another one for the fractional part is more than enough!

I can understand having a 3rd byte if you don't want to manually extend the top byte when doing calculations, but then the 3rd byte will always be either $00 (positive values) or $FF (negative values).

Normally you'd define the constant as the full 16-bit (or 24-bit) value, instead of splitting it in bytes, and then extract the individual bytes from that. This way you can negate the values before extracting the individual bytes if you need the negative version of the value:

Code: Select all

ACCELERATION = $0180

;use positive acceleration
lda #<ACCELERATION
sta ax+0
lda #>ACCELERATION
sta ax+1

;use negative acceleration
lda #<(-ACCELERATION)
sta ax+0
lda #>(-ACCELERATION)
sta ax+1
Most assemblers have fast ways of accessing the low and high bytes of a value, but I'm not sure how you'd go about accessing a third byte... you may need to use bitmasks and bitshifting.
calima
Posts: 1745
Joined: Tue Oct 06, 2015 10:16 am

Re: Calculating negative of 3 byte constants

Post by calima »

ca65's third byte operator is ^.
Siev
Posts: 4
Joined: Sun Apr 25, 2021 10:55 pm

Re: Calculating negative of 3 byte constants

Post by Siev »

Turns out I was actually using dasm.
For future reference this is how I'm doing it now:

Code: Select all

GRAVITY	        = $012000

        lda #<(GRAVITY)
        sta ay2
        lda #>(GRAVITY)
        sta ay1  
	lda #>(GRAVITY>>8)
        sta ay0
and as said in ca65 you can use ^ for accessing the third byte (aka bank byte). Thank you both.
Post Reply