# 8 Bit Twice Shy aka Size Does Matter

#### neilobremski

##### Experienced Member
I've been working with 8-bit fixed point for pre-calculated SINE and COSINE values. One compromise of this is that the maximum positive value is only 127 which means I can only represent 127/128 (0.9921875) and not a whole ONE.

Recently I encountered an odd bug where viewing my tile map from a 270° facing caused the Z coordinates of all objects to be reversed. My test map and player position looked like so:

Code:
``````P
P <``````

And thus I expected to see the following:

But instead it was blank. I decided the view (position) rotation algorithm must be bogus and reworked it from scratch. I tested it with the following JScript on my Windows computer:

Code:
``````function cos(degrees)
{
return Math.round(Math.cos(Math.PI * degrees / 180.0) * 100) / 100;
}

function sin(degrees)
{
return Math.round(Math.sin(Math.PI * degrees / 180.0) * 100) / 100;
}

function turn(x,y, degrees)
{
var xr = (x * cos(degrees)) - (y * sin(degrees));
var yr = (y * cos(degrees)) + (x * sin(degrees));
WScript.Echo("TURN: " + xr + " , " + yr);
}

function view(x,y, degrees)
{
var xr = (x * cos(degrees)) - (y * -sin(degrees));
var yr = -((y * cos(degrees)) + (x * -sin(degrees)));
WScript.Echo("VIEW: " + xr + " , " + yr);
}

var x = parseFloat(WScript.Arguments.Item(0).toString());
var y = parseFloat(WScript.Arguments.Item(1).toString());
var degrees = parseFloat(WScript.Arguments.Item(2).toString());

turn(x,y,degrees);

view(x,y,degrees);``````

NOTE that Y is negated for use as Z since positive Z is "in front" and negative is "in back" of the camera. Redoing the algorithm only caused me more alarm because it looked suspiciously like what I had had before:

Code:
``````;	Zt = ((Yr * cos(dir)) + (Xr * -sin(dir))) * -128
;	Xt = ((Xr * cos(dir)) - (Yr * -sin(dir))) * 128``````

So why then wasn't it working? I stepped through the code and found the answer in the 8-bit fixed point. See if you can spot it ...

Code:
``````MOV	AX, BP	; 5EA
MOV	AL, AH	; 5EC  AL = cos(dir)
IMUL	BL	; 5EE Yr * cos(dir)
MOV	DX, AX	; 5F0
MOV	AX, BP	; 5F2
NEG	AL	; 5F4 AL = -sin(dir)
IMUL	BH	; 5F6 Xr * -sin(dir)
NEG	AX	; 5FA * -128
STOSW		; 5FC write [  Zt  ]``````

The SINE value of 270 degrees is -1 which in 8-bit fixed point is 0x80 or -128. This cannot be negated because there is no +128! And since the two's complement does nothing the value remains the same. Remember I am truncating positive values to +127 or 0x7F and doing that logically would incur a lot of extra instructions ... or I could simply negate the 16-bit value resulting from IMUL ...

Code:
``````MOV	AX, BP	; 5EA
MOV	AL, AH	; 5EC
IMUL	BL	; 5EE Yr * cos(dir)
MOV	DX, AX	; 5F0
MOV	AX, BP	; 5F2
IMUL	BH	; 5F4 Xr * -sin(dir)
NEG	AX	; 5F6
NEG	AX	; 5FA * -128
STOSW		; 5FC write [  Zt  ]``````

That works but there are two NEG's surrounding an ADD which is redundant. I finally reduced this code to the following which works beautifully ...

Code:
``````MOV	AX, BP	; 5EA
MOV	AL, AH	; 5EC
IMUL	BL	; 5EE Yr * cos(dir)
MOV	DX, AX	; 5F0
MOV	AX, BP	; 5F2
IMUL	BH	; 5F4 Xr * -sin(dir)
NEG	DX	; 5F6