IGNORED

## Recommended Posts

Hello there. Noob here. I'm currently working through a book called Programming Games for Atari 2600 by Oscar Toledo G., and I'm stuck trying to understand how this fine positioning subroutine example actually works.

To be clear, it does work. When I assemble the code and run the bin in Stella, everything is functioning as it should. I'm just having trouble connecting the dots in my mind, as it's not exactly spelled out.

The part that's not making sense to me is how the "LDA FINE_ADJUST-\$F1,Y" interacts with the FINE_ADJUST table. For instance, in this demo, you're sent to the subroutine with #76 loaded into the A register as the desired X position. From my understanding, 76 is then divided by 15 via SBC until you're left with a remainder of 1. From there, it looks like 1 is loaded into the Y register, which is then used to increment FINE_ADJUST-\$F1 by 1. If that's the case, how do we end up

at .byte \$F0, which moves us 1px to the right and into the desired fine position of 76?

Apologies if I'm missing something completely obvious or interpreting the instructions incorrectly. I've taken a course on Udemy from Gustavo Pezzi that handled this operation in a different way, which clicked pretty easily. I believe Steven Hugg also presented the same approach in his book Making Games for the Atari 2600. However, I don't like encountering this other method and leaving it up in the air as magical lol. So if you can help to fill in the gaps I would greatly appreciate it!

##### Share on other sites

I believe the SBC #15 / BCS X_P1 "divide by subtraction" loop actually does one extra subtract, so you end up with a remainder number between \$F1..\$FF.  This is what ends up in the Y register, so, the FINE_ADJUST data lookup uses the address of 'FINE_ADJUST-\$F1' to compensate.

##### Share on other sites

51 minutes ago, SUPERDIVORCE said:

From my understanding, 76 is then divided by 15 via SBC until you're left with a remainder of 1.

Nope.  15 is subtracted from 76 until it goes below zero, giving you -14.  Which is \$F2.  So \$F2 is loaded into Y, which indexes like LDA \$FE00,Y which loads from the table that spans from \$FEF1 - \$ FEFF.

It gets the same values as the horizontal position routines that use shifting, but this one loads from a table instead.

##### Share on other sites

I'm still trying to grasp the concept of how SBC and negatives work in various situations. I thought the remainder was what you're left with when you can't successfully subtract without going negative, but it seems like you're saying that's not correct. Is that always the case?

Also, in this case, if you have a value of #1 and subtract #15 again, is there an easy way to explain how that would give you a remainder between \$F1-\$FF?

##### Share on other sites

6 minutes ago, glurk said:

15 is subtracted from 76 until it goes below zero, giving you -14.  Which is \$F2.  So \$F2 is loaded into Y, which indexes like LDA \$FE00,Y which loads from the table that spans from \$FEF1 - \$ FEFF.

Thanks for clarifying. I haven't worked with negative values much, so I'm still trying to make sense of how these numbers are converted into hex.

As for the table, is each byte representing a range as opposed to a single hex number? If so, do all values between F0-FF mean a move 1px to the right? Values between \$E0-EF = move 2px to the right. Etc?

##### Share on other sites

Negatives in hex are 2's complement. but it's easy...

2  = \$02

1  = \$01

0  = \$00

-1 = \$FF

-2 = \$FE

etc...

And in the table, the HMxx values only use the high nybble, or upper 4 bits, so the lower value is not used at all.  So the last digits in the table values could be anything, even used as another table for some other use.

##### Share on other sites

10 hours ago, glurk said:

Negatives in hex are 2's complement. but it's easy...

2  = \$02

1  = \$01

0  = \$00

-1 = \$FF

-2 = \$FE

etc...

And in the table, the HMxx values only use the high nybble, or upper 4 bits, so the lower value is not used at all.  So the last digits in the table values could be anything, even used as another table for some other use.

Thanks! That really helps to clear things up!

##### Share on other sites

@nanochess Oscar Toledo G. is the author and a member here. Looks like your question was answered but he might like to see this thread.

##### Share on other sites

8 minutes ago, Big Player said:

@nanochess Oscar Toledo G. is the author and a member here. Looks like your question was answered but he might like to see this thread.

I was actually able to get in touch with him on Twitter and he was happy to help.

##### Share on other sites

On 1/18/2023 at 9:08 PM, splendidnut said:

I believe the SBC #15 / BCS X_P1 "divide by subtraction" loop actually does one extra subtract, so you end up with a remainder number between \$F1..\$FF.  This is what ends up in the Y register, so, the FINE_ADJUST data lookup uses the address of 'FINE_ADJUST-\$F1' to compensate.

Yes, this is right in part.

There's no thing like one extra subtraction. Instead, it depends on doing subtraction until it hits borrow.

Let us suppose the subtraction instruction was SBC #1, for this loop you would always end with a value of \$ff (\$00 - \$01 = \$ff).

For SBC #2, you would always end with a value of \$fe or \$ff (\$00 - \$02 or \$01 - \$02)

Extrapolating, for SBC #15 the value would be in the range \$f1-\$ff.

We need a value in the range \$00-\$0e to index into our table, but we don't have enough time to execute an ADC #\$0f instruction (I mean ADC #\$0F / TAY / LDA fine_adjust,Y)

I hope this helps @SUPERDIVORCE

## 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.

×   Pasted as rich text.   Paste as plain text instead

Only 75 emoji are allowed.