Jump to content
IGNORED

Convert fraction to base 256


SeaGtGruff

Recommended Posts

(Please note that this thread corrects and supercedes the erroneous information I'd previously posted in the "Quick animation question" and "Function: Divide 16 bits by 8 bits" threads!)

 

I'm not sure if the title of this new topic is the proper way to describe it, but what it's about is when you have two unsigned 1-byte/8-bit integers, and you want to divide them to get a fraction, but you want the fraction to be a fraction of 256.

 

There are two ways you can divide integers in batari Basic-- with the "/" operator, and with the "//" operator. Using "/" will return an 8-bit integer quotient, but with no remainder. Using "//" also returns an 8-bit integer quotient, but the remainder is put into temp1 in case you want to retrieve it.

 

At first glance, the "//" operator would seem to be the answer for situations like the one described in the "Quick animation question" thread, where you want to calculate the slope of a line using an 8.8 fixed-point variable, and then move a sprite along that slope. However, when you use the "//" operator, the remainder is a fraction of the original divisor. For example, if you divide 2 by 3, then the remainder will be a fraction of 3. That's no good for the slope situation, because in an 8.8 fixed-point variable, the fractional portion is a fraction of 256. So what we really want is a routine that divides two integers, and returns the fractional portion as a fraction of 256.

 

Happily, I found just such a routine at the "6502.org Wiki." But unhappily, I misunderstood what the routine does, due to its somewhat-misleading description-- "16-bit / 8-bit = 8-bit quotient, 8-bit remainder (unsigned)." But once I understood the routine a little better, I realized that with a few very minor changes, it's perfect for what we want to do-- namely, divide two 8-bit unsigned integers, where the numerator is less than the divisor, and express the result as a fraction of 256!

 

Note that phrase-- "where the numerator is less than the divisor"-- because it's important.

 

After revising and renaming the original routine, and stumbling around a bit, I finally managed to create a demo program that uses the function to move player1 around the screen after player0. I don't claim that the demo shows the best way to do this, but I think the results are kind of nifty.

 

As an added bonus, this demo program also uses a joystick routine that you might find interesting, because it eliminates the need for all the usual "if joy0up" and "if joy0down" types of statements. Basically, all four bits of the joystick directional switches-- excluding the fire button-- are stored in the lo-nybble of a single byte, giving a value between 0 and 15 that can be used as an index into two data arrays for the x motion and y motion increments. This seems so obvious that I'd expect it's been used before (in assembly code), but I haven't seen it used before-- although I don't study other people's code, so the fact that I'm unaware of anyone ever doing this doesn't mean squat!

 

Anyway, the revised function is nearly identical to the original version, but it uses only two temp variables instead of three, it's been renamed to "fraction256" so it better describes what it does, and the fractional portion is returned in temp1 instead of temp2. Since the function is intended to be used only for dividing a smaller numerator by a larger divisor, temp2 is set to 0 when the function is finished, and temp2 (or 0) is returned back to the calling statement via the accumulator.

 

This demo program defines (or "dim"s) nine different variables-- three of which are 8.8 fixed-point variables-- but most of the variables are of a temporary nature, so I "dim"med them using temp1 through temp6. Only three user variables are used-- a, b, and c-- and one of them ( c) is used as an "odd-even" frame counter, so only two user variables would be used if I weren't keeping track of the frame. The reason for tracking the frame is so player0 can be moved each frame, while moving player1 only every other frame, so that player1 will always lag behind player0.

 

Use the left joystick to move the red "X" (player0) around the screen, and the blue rectangle (player1) will chase it, always moving along a straight (sloped) line between the two players. I won't try to explain the code any further right now, but will try to answer any questions about it as best I can.

 

However, I will say one more thing, because it gave me so many problems while I was trying to debug the demo program. When using 8.8 fixed-point variables, you need to be careful how you use them in assignment statements. If you want to set both bytes of the variable, you should generally include a decimal point in the value, or the assignment statement may not work as you expect. Also, if you want to set just the hi-byte of the variable, it's generally best to reference the specific 1-byte variable that's being used for the hi-byte, otherwise the results may not be what you expect.

 

Michael

move_sprite_on_a_slope.bas

move_sprite_on_a_slope.bas.bin

Edited by SeaGtGruff
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...