Skip to main content
← PSoXide SDK guides and examples · SDK f2fec1c301f1 · All Cargo features enabled; check feature gates before use.

psx_math/
lib.rs

1// SPDX-License-Identifier: GPL-2.0-or-later
2//! Fixed-point math primitives for the PS1 SDK.
3//!
4//! The PS1 has no FPU. Games that want sine-driven animation,
5//! camera rotation, pseudo-3D, or smoothed HUDs all reach for the
6//! same toolbox: a Q-format fixed-point type, a sin/cos LUT, and
7//! a couple of vector/matrix helpers. This crate owns those
8//! primitives once so every downstream crate (`psx-font`, a
9//! future `psx-gte`-wrapper, a future `psx-ui`, gameplay code)
10//! shares the same representation.
11//!
12//! ## What's here today
13//!
14//! - [`sincos`] -- Q0.12 angle type + 256-entry Q1.12 sine LUT +
15//!   interpolated `sin_q12` / `cos_q12` lookups, and the matching
16//!   octant-linear `atan2_q12`.
17//! - [`int32`] -- saturating 32-bit scalar helpers: `abs_i32` /
18//!   `abs_i16`, `clamp_i16`, `square_i32_saturating`, `isqrt_i32`,
19//!   `mul_q12_i32`, plus the 64-bit-free wide forms `mul_div_i32`,
20//!   `mul_shr_i32`, `mul_shr_trunc_i32`, `mul_div_u32`, `isqrt_u64` and
21//!   `div_u64_by_u32`.
22//! - [`fmt`] -- integer-to-decimal ASCII without `core::fmt`, for
23//!   HUD/score text drawn with `psx-font`.
24//!
25//! ## What's planned (same crate, future modules)
26//!
27//! - `fixed` -- Q3.12 and Q16.16 wrappers with operator overloads
28//!   and saturating / wrapping arithmetic.
29//! - `vec` -- `Vec2` / `Vec3` over integer and fixed-point types
30//!   with dot / cross / length² / normalise.
31//! - `mat` -- 2×2 / 3×3 / GTE-shape matrices, chosen to match how
32//!   the GTE's `RTPS` / `MVMVA` instructions consume data.
33//! - `ease` -- sinusoidal / quadratic / cubic easing helpers for
34//!   timeline animation.
35//! - `lerp` -- generic linear interpolation.
36//!
37//! These modules land as concrete consumer code needs them -- no
38//! premature abstractions. The crate ships empty apart from the
39//! documented scope so reviewers can see where new primitives
40//! should go.
41//!
42//! ## Q-format refresher
43//!
44//! `Qm.n` means `m` integer bits + `n` fractional bits in a
45//! signed integer. Arithmetic rules:
46//!
47//! - Add / sub: same as ordinary integer add / sub.
48//! - Multiply: `(a * b) >> n` -- two Q_._n values produce a Q_._2n
49//!   intermediate that must be shifted back.
50//! - Divide: `(a << n) / b` -- scale up the numerator by `n` bits
51//!   first so the quotient is in Qm.n.
52//!
53//! Conventions the PS1 SDK uses:
54//!
55//! - **Q0.12 angle**: `u16` in `[0, 4096)` maps to `[0°, 360°)`.
56//!   Matches the GTE's angle resolution. `4096` = one full
57//!   revolution. Overflow wraps naturally in u16.
58//! - **Q1.12 trig values**: `i16` in `[-4096, 4096]`. `4096` =
59//!   +1.0, `-4096` = -1.0. Multiplying a Q_._12 input by a Q1.12
60//!   coefficient produces a Q_._24 intermediate; shift right 12
61//!   to land back in the original format.
62//! - **Q3.12 transforms** (future): `i16` with range `±7.999…`.
63//!   Used by `psx-font`'s affine matrices today; planned as a
64//!   proper `Mat2` type here.
65//! - **Q16.16 positions** (future): `i32` in `±32767` with 16
66//!   fractional bits -- standard precision for sub-pixel
67//!   positions, accumulated velocities, etc.
68
69#![no_std]
70#![deny(unsafe_op_in_unsafe_fn)]
71#![warn(missing_docs)]
72
73pub mod attributed_clip;
74pub mod color;
75pub mod fmt;
76pub mod int32;
77pub mod sincos;
78
79// Re-export the most common symbols at the crate root so users
80// can `use psx_math::{sin_q12, cos_q12}` without reaching through
81// the submodule -- these are the hot-loop primitives.
82pub use sincos::{atan2_q12, cos_q12, sin_q12, SIN_TABLE};