• Please review our updated Terms and Rules here

Sine here for 7 Bits

neilobremski

Experienced Member
Joined
Oct 9, 2016
Messages
55
Location
Seattle, USA
It's time to take the time to make a post to mark my progress. Previously I had mentioned doing sine and cosine multiplications using fixed-point, specifically 10-bit so that the whole unsigned fraction could fit in a single byte. I thought this would be sufficient and it was but it also turned out to still be more than necessary. On top of that, using word multiplications ties up a lot more registers.

So I did two things: first I dropped down to using a single byte to store the entire fixed point value. This usually leaves only 6 bits for the unsigned fraction portion but the second thing I did was to dare to use 7. The result is fixed point numbers which can express -1 but not a pure +1, because zero counts on the positive side and so the range is always -N^2 to N^2 - 1. Thus with 7 bits, the range is -128 to +127 and my fixed point range is -1.00 to +0.99.

Obviously I was worried that this would not be enough precision but on paper it looked okay and when I finally got it all coded and visually demonstrated, I was pleased to see it worked fine. I added some rounding code to so that the positive sine/cosine multiplications come out correct for the angles I need them to. [SUP][1][/SUP]

The following assembly multiplies a whole signed integer in AL by one of the sine/cosine fixed point values in AH (or the opposite order since multiplication is commutative).

Code:
IMUL	AH	;
SAL	AX, 1	; afterwards AH = truncated whole result
ROL	AL, 1	;
AND	AL, 1	; AL is now a rounding carry
ADD	AL, AH	; add carry to round up

This won't work properly for negative rounding but that hasn't stopped me from using it successfully to rotate stuff. Check it out:

View attachment 38958 View attachment 38960
(Click image to see animated version))​

Some other cool things about using a 128 denominator is that the fractions it represents are at least two decimal points so it's a bit easier to do on paper. And also, my 3D tile sizes are 128 as well which means that rotating a tile from it's 2D 8-bit coordinates will result in a proper 3D 16-bit coordinate with a single multiplication. More on this in my next post about the square raycast ...

Footnotes:
[SUP][1][/SUP]. I'm working with angles in multiples of 10 degrees.
 
This reminds me of a school friend of mine who wrote a version of Battlezone for his Apple ][ in 6502 assembler, about 35 years ago. From memory the 3D calcs were done with 256-byte integer lookup tables for sines and cosines, multiplied by 256. He also had his own machine code line drawing routines. It worked amazingly well, with the green wireframe tanks and obstacles moving pretty smoothly against the mountain background similar to the actual Battlezone vector display. I don't recall he ever finished it as a complete game though, impressive as it was.
 
Back
Top