SNES Fixed-Point Math. More...
#include <snes/types.h>Go to the source code of this file.
Macros | |
| #define | FIX(x) |
| Convert integer to fixed-point. | |
| #define | FIX_FRAC(x) |
| Get fractional part of fixed-point. | |
| #define | FIX_MAKE(i, f) |
| Create fixed-point from integer and fraction. | |
| #define | UNFIX(x) |
| Convert fixed-point to integer (truncate). | |
| #define | UNFIX_ROUND(x) |
| Convert fixed-point to integer (rounded). | |
Typedefs | |
| typedef s16 | fixed |
| 8.8 signed fixed-point type | |
Functions | |
| u8 | atan2_8 (s16 dy, s16 dx) |
| 8-bit two-argument arctangent | |
| u16 | div16 (u16 dividend, u16 divisor) |
| Safe 16-bit division. | |
| u8 | ease_in_quad (u8 t) |
| Ease-in quadratic: t² curve, output [0, 255]. | |
| u8 | ease_out_quad (u8 t) |
| Ease-out quadratic: 1 - (1-t)² curve, output [0, 255]. | |
| fixed | fixAbs (fixed x) |
| Absolute value of fixed-point. | |
| fixed | fixClamp (fixed x, fixed min, fixed max) |
| Clamp value to range. | |
| fixed | fixCos (u8 angle) |
| Get cosine value for angle. | |
| fixed | fixDiv (fixed a, fixed b) |
| Divide two fixed-point values. | |
| fixed | fixLerp (fixed a, fixed b, u8 t) |
| Linear interpolation. | |
| fixed | fixMul (fixed a, fixed b) |
| Multiply two fixed-point values. | |
| fixed | fixSin (u8 angle) |
| fixed | fixSqrt (fixed x) |
| Square root in 8.8 fixed-point. | |
| u16 | mod16 (u16 dividend, u16 divisor) |
| Get remainder of division. | |
| u16 | mul16 (u16 a, u16 b) |
| Safe 16-bit multiplication. | |
| u16 | sqrt16 (u16 n) |
| Integer square root. | |
Variables | |
| const u8 | ease_quad_table [256] |
| 256-byte quadratic easing LUT — i² normalised to [0, 255] | |
| const s16 | sine_table [256] |
| Get sine value for angle. | |
SNES Fixed-Point Math.
Fixed-point arithmetic for smooth movement and physics.
This module provides:
The fixed type is 16-bit signed (s16) in 8.8 format:
Angles are 8-bit values (0-255) representing 0-360 degrees:
| #define FIX | ( | x | ) |
| #define FIX_FRAC | ( | x | ) |
Get fractional part of fixed-point.
| x | Fixed-point value |
| #define FIX_MAKE | ( | i, | |
| f ) |
Create fixed-point from integer and fraction.
| i | Integer part |
| f | Fractional part (0-255) |
| #define UNFIX | ( | x | ) |
| #define UNFIX_ROUND | ( | x | ) |
Convert fixed-point to integer (rounded).
| x | Fixed-point value |
8.8 signed fixed-point type
Range: -128.0 to 127.996 (approximately) Precision: 1/256 = 0.00390625
8-bit two-argument arctangent
Returns the angle of the vector (dx, dy) measured from the positive X axis, in the SDK's 8-bit angle convention (0–255 = 0°–360°, same scale as fixSin / fixCos).
Implementation: 65-entry LUT covering the first octant (atan(t) for t ∈ [0, 1] mapped to angle [0, 32]), with symmetry handling for the other 7 octants. Inputs are reduced by power-of-two right shifts when their magnitudes exceed 255, so the function works for any 16-bit signed input without overflowing the internal 16-bit divide.
| dy | Y component of the vector |
| dx | X component of the vector |
Safe 16-bit division.
Bounded binary long division — always 16 iterations regardless of the operands, so the cost is predictable. (A future optimisation could use the hardware divider at $4204-$4206 for divisors up to 255.)
| dividend | Number to divide |
| divisor | Number to divide by (must not be zero) |
Ease-in quadratic: t² curve, output [0, 255].
| t | Input in [0, 255] |
Canonical animation curve. Use to drive a value from 0 to its final state over N frames where the motion feels "wound up" at the start:
Ease-out quadratic: 1 - (1-t)² curve, output [0, 255].
| t | Input in [0, 255] |
Mirror of ease_in_quad. Use when the motion should "decelerate" into its final state (e.g., a sprite sliding into position).
Absolute value of fixed-point.
| x | Fixed-point value |
Clamp value to range.
| x | Value to clamp |
| min | Minimum value |
| max | Maximum value |
Divide two fixed-point values.
Multiply two fixed-point values.
Square root in 8.8 fixed-point.
Computes the square root of an 8.8 fixed-point value. Internally delegates to sqrt16(x) and shifts the result by 4 bits to recover 5 bits of fractional precision in the answer (the remaining 3 bits are zero — this is a lib-side limit, not a mathematical one; precision can be raised once the QBE 32-bit codegen lands — see chantier A7 in the structural-defects catalogue).
| x | Input value in 8.8 fixed-point. Must be ≥ 0; negative inputs return 0. |
Get remainder of division.
Same bounded binary long division as div16() — always 16 iterations.
| dividend | Number to divide |
| divisor | Number to divide by (must not be zero) |
Safe 16-bit multiplication.
Multiplies two 16-bit values safely. Use this instead of the compiler's * operator for important calculations, as the compiler's runtime multiplication can have bugs.
Integer square root.
Computes floor(sqrt(n)) for any 16-bit unsigned input. Uses the canonical bit-by-bit (digit-by-digit) algorithm — no LUT, no floating point, fully deterministic in cycle count (~80 cycles worst case on the 65816).
| n | Input value (0 to 65535) |
|
extern |
256-byte quadratic easing LUT — i² normalised to [0, 255]
ease_quad_table[i] = floor(i² / 255). Underlies ease_in_quad and ease_out_quad. Lives in the opt-in math_ease module (LIB_MODULES += math_ease) so math users who don't ease don't pay its 256 bank-$00 bytes. Exposed as extern so user code can index it directly for custom curve compositions.
Cost: ~5 cycles per lookup vs ~12 for (x * x) / 255 live. ROM cost: 256 bytes (placed in a SUPERFREE section by the linker).