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
99#define UNFIX32(x) ((s16)((fixed32)(x) >> 16))
100
111#define FIX32_FRAC(x) ((u16)((fixed32)(x) & 0xFFFF))
112
123#define FIX32_MAKE(i, f) (((fixed32)(s16)(i) << 16) | (fixed32)(u16)(f))
124
125/*============================================================================
126 * Inline operations (no asm needed — compiler emits Kl arithmetic)
127 *============================================================================*/
128
139 return x < 0 ? -x : x;
140}
141
149 if (x < min) return min;
150 if (x > max) return max;
151 return x;
152}
153
158 return a < b ? a : b;
159}
160
165 return a > b ? a : b;
166}
167
168/*============================================================================
169 * ASM-backed multiply
170 *============================================================================*/
171
192
213
240 return a + fix32Mul(b - a, t);
241}
242
243/*============================================================================
244 * Trigonometry (lifted from 8.8 LUT, 8 fractional bits of precision)
245 *============================================================================*/
246
267/* Implemented in lib/source/fixed32.asm. Two qbe codegen bugs make the
268 * one-line C body `(u32)(s32)fixSin(angle) << 8` produce wrong results:
269 *
270 * 1. Kl shift-by-constant spill (fixed in qbe 2026-05-22): the high
271 * half was computed from an unstored stack slot. Resolved.
272 *
273 * 2. Kw → Kl widening sign assumption (UNFIXED): ref_is_high_zero()
274 * treats all Kw operands as zero-extended. Wrong for signed
275 * s16 → s32 — produces 0x00FF0000 instead of 0xFFFF0000 for
276 * sin(270°) = -1.
277 *
278 * The asm form sign-extends explicitly and avoids both. See
279 * lib/source/math.c for the full notes. */
282
291/* fix32Cos declared above with fix32Sin — both bodies in math.c. */
292
293#endif /* OPENSNES_FIXED32_H */
fixed32 fix32Max(fixed32 a, fixed32 b)
Maximum of two fixed32.
Definition fixed32.h:164
fixed32 fix32Lerp(fixed32 a, fixed32 b, fixed32 t)
16.16 fixed-point linear interpolation
Definition fixed32.h:239
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:148
fixed32 fix32Min(fixed32 a, fixed32 b)
Minimum of two fixed32.
Definition fixed32.h:157
fixed32 fix32Abs(fixed32 x)
Absolute value of a fixed32.
Definition fixed32.h:138
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:157
static u16 a
Definition main.c:157
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
Rotation step index, 0..47.
Definition main.c:53
OpenSNES Standard Types.