Jump to content
IGNORED

Can someone please explain how this fine adjustment subroutine works?


SUPERDIVORCE

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!

 

Sub.png

Link to comment
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.

  • Like 1
Link to comment
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?

Link to comment
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?

Link to comment
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.

  • Like 1
Link to comment
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!

Link to comment
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)

 

So instead we adjust the address by subtracting $f1 in order to get the right address LDA fine_adjust-$F1,Y.

 

I hope this helps @SUPERDIVORCE

 

  • Like 1
Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...