OpenSNES
Modern Open-Source SNES Development SDK
Loading...
Searching...
No Matches
fixed32.h
Go to the documentation of this file.
1
51
52#ifndef OPENSNES_FIXED32_H
53#define OPENSNES_FIXED32_H
54
55#include <snes/types.h>
56#include <snes/math.h> /* for fixSin / fixCos (8.8 LUT) */
57
58/*============================================================================
59 * Type and macros
60 *============================================================================*/
61
68typedef s32 fixed32;
69
80/* Cast through u32 before shifting to avoid the C UB on left-shifting a
81 * negative signed value. Final cast back to fixed32 preserves bit pattern. */
82#define FIX32(x) ((fixed32)((u32)(s32)(x) << 16))
83
98#define UNFIX32(x) ((s16)((fixed32)(x) >> 16))
99
110#define FIX32_FRAC(x) ((u16)((fixed32)(x) & 0xFFFF))
111
122#define FIX32_MAKE(i, f) (((fixed32)(s16)(i) << 16) | (fixed32)(u16)(f))
123
124/*============================================================================
125 * Inline operations (no asm needed — compiler emits Kl arithmetic)
126 *============================================================================*/
127
138 return x < 0 ? -x : x;
139}
140
148 if (x < min) return min;
149 if (x > max) return max;
150 return x;
151}
152
157 return a < b ? a : b;
158}
159
164 return a > b ? a : b;
165}
166
167/*============================================================================
168 * ASM-backed multiply
169 *============================================================================*/
170
197
221
249 return a + fix32Mul(b - a, t);
250}
251
252/*============================================================================
253 * Trigonometry (lifted from 8.8 LUT, 8 fractional bits of precision)
254 *============================================================================*/
255
277/* Implemented in lib/source/fixed32.asm. It was written that way because
278 * two qbe codegen bugs made the one-line C body
279 * `(u32)(s32)fixSin(angle) << 8` produce wrong results — a Kl
280 * shift-by-constant spill (fixed 2026-05-22) and a sign assumption on
281 * widening, which produced 0x00FF0000 instead of 0xFFFF0000 for
282 * sin(270°) = -1.
283 *
284 * BOTH ARE GONE (re-measured 2026-09-18). `testing/fixtures/libtests` now computes
285 * that exact C expression alongside this function and asserts they agree
286 * (r_f32sin_c / r_f32sin_asm), and `c_features` pins the widen-then-shift
287 * case on its own (r_widen_shl). The asm stays because there is no reason
288 * to churn a working routine, not because C cannot express it. */
297
306/* fix32Cos declared above with fix32Sin — both bodies in fixed32.asm. */
307
308#endif /* OPENSNES_FIXED32_H */
fixed32 fix32Max(fixed32 a, fixed32 b)
Maximum of two fixed32.
Definition fixed32.h:163
fixed32 fix32Lerp(fixed32 a, fixed32 b, fixed32 t)
16.16 fixed-point linear interpolation
Definition fixed32.h:248
fixed32 fix32Mul(fixed32 a, fixed32 b)
16.16 fixed-point multiply
s32 fixed32
16.16 signed fixed-point type
Definition fixed32.h:68
fixed32 fix32Div(fixed32 a, fixed32 b)
16.16 fixed-point divide
fixed32 fix32Clamp(fixed32 x, fixed32 min, fixed32 max)
Clamp x to [min, max].
Definition fixed32.h:147
fixed32 fix32Min(fixed32 a, fixed32 b)
Minimum of two fixed32.
Definition fixed32.h:156
fixed32 fix32Abs(fixed32 x)
Absolute value of a fixed32.
Definition fixed32.h:137
fixed32 fix32Sin(u8 angle)
16.16 fixed-point sine of an 8-bit angle (0..255 = 0..360°)
fixed32 fix32Cos(u8 angle)
static u16 b
Definition main.c:156
static u16 a
Definition main.c:156
signed int s32
32-bit signed integer (-2147483648 to 2147483647)
Definition types.h:79
unsigned char u8
8-bit unsigned integer (0 to 255)
Definition types.h:47
SNES Fixed-Point Math.
static u16 angle
Mode 7 ground: 9-tile prefab track (original art).
Definition main.c:46
OpenSNES Standard Types.