gfxd_rs/
new_types.rs

1/* SPDX-FileCopyrightText: © 2025 Decompollaborate */
2/* SPDX-License-Identifier: MIT OR Apache-2.0 */
3
4use core::fmt;
5
6/// An address pointed to by a `Gfx` macro.
7#[derive(Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
8pub struct Address(pub u32);
9
10impl fmt::Debug for Address {
11    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
12        write!(f, "Address(0x{:08X})", self.0)
13    }
14}
15
16impl fmt::Display for Address {
17    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
18        write!(f, "{:08X}", self.0)
19    }
20}
21
22/// How many colors a TLUT has.
23///
24/// The most common ones are `Pal16` and `Pal256`.
25#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
26pub enum TlutCount {
27    /// 16 colors TLUT. Usually paired with CI4 textures.
28    Pal16,
29    /// 256 colors TLUT. Usually paired with CI8 textures.
30    Pal256,
31    /// Any other amount of colors. Very unusual.
32    // This value is 14 bits wide, so a u16 is more than enough.
33    Other(u16),
34}
35
36impl TlutCount {
37    pub(crate) const fn new(value: i32) -> Self {
38        match value {
39            16 => Self::Pal16,
40            256 => Self::Pal256,
41            x => {
42                #[allow(clippy::cast_possible_truncation)]
43                let x = x as _;
44                Self::Other(x)
45            }
46        }
47    }
48}
49
50/// The format of a texture.
51#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
52pub enum TexFmt {
53    /// Explicit Red/Green/Blue/Alpha textures.
54    ///
55    /// Only supported with [`Siz16b`] and [`Siz32b`].
56    ///
57    /// [`Siz16b`]: TexSiz::Siz16b
58    /// [`Siz32b`]: TexSiz::Siz32b
59    Rgba,
60    /// Luminance (Y) and two chrominance (UV).
61    ///
62    /// Only supported with [`Siz16b`].
63    ///
64    /// [`Siz16b`]: TexSiz::Siz16b
65    Yuv,
66    /// Color indexed textures.
67    ///
68    /// Only supported with [`Siz8b`] and  [`Siz4b`].
69    ///
70    /// [`Siz8b`]: TexSiz::Siz8b
71    /// [`Siz4b`]: TexSiz::Siz4b
72    CI,
73    /// Intensity with Alpha textures.
74    ///
75    /// Only supported with [`Siz16b`], [`Siz8b`] and  [`Siz4b`].
76    ///
77    /// [`Siz16b`]: TexSiz::Siz16b
78    /// [`Siz8b`]: TexSiz::Siz8b
79    /// [`Siz4b`]: TexSiz::Siz4b
80    IA,
81    /// Intensity textures.
82    ///
83    /// Only supported with [`Siz8b`] and  [`Siz4b`].
84    ///
85    /// [`Siz8b`]: TexSiz::Siz8b
86    /// [`Siz4b`]: TexSiz::Siz4b
87    I,
88    /// Other raw values.
89    // This value is 3 bits wide, so a u8 is more than enough.
90    Other(u8),
91}
92
93impl TexFmt {
94    pub(crate) const fn new(value: i32) -> Self {
95        match value {
96            0 => Self::Rgba,
97            1 => Self::Yuv,
98            2 => Self::CI,
99            3 => Self::IA,
100            4 => Self::I,
101            x => {
102                #[allow(clippy::cast_possible_truncation)]
103                let x = x as _;
104                Self::Other(x)
105            }
106        }
107    }
108}
109
110/// The bit size of a texture.
111// This value is 2 bits wide, so the enum should exhaust every posibility.
112#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
113pub enum TexSiz {
114    /// 4 bit per pixel.
115    Siz4b,
116    /// 8 bit per pixel.
117    Siz8b,
118    /// 16 bit per pixel.
119    Siz16b,
120    /// 32 bit per pixel.
121    Siz32b,
122}
123
124impl TexSiz {
125    pub(crate) fn new(value: i32) -> Self {
126        match value {
127            0 => Self::Siz4b,
128            1 => Self::Siz8b,
129            2 => Self::Siz16b,
130            3 => Self::Siz32b,
131            x => unreachable!(
132                "Oh, this shouldn't have had happen. Could you make a bug report? Value: {}",
133                x
134            ),
135        }
136    }
137}
138
139/// How many macro packets the current macro actually refers to.
140#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
141pub enum LookatCount {
142    /// This macro does not correspond to a complete `gsSPLookAt`, but instead
143    /// is a singular use of either `gsSPLookAtX` or `gsSPLookAtY`.
144    N1 = 1,
145    /// This macro is a complete `gsSPLookAt` macro.
146    N2 = 2,
147}
148
149impl LookatCount {
150    pub(crate) fn new(value: i32) -> Self {
151        match value {
152            1 => Self::N1,
153            2 => Self::N2,
154            // SAFETY: This is a value made by gfxd, not decoded from a macro,
155            // and we already cover every possible value, so if we reach this
156            // part it means gfxd itself update itself to add new values.
157            x => unreachable!(
158                "Oh, this shouldn't have had happen. Could you make a bug report? Value: {}",
159                x
160            ),
161        }
162    }
163}
164
165/// `NUMLIGHTS_0` is absent from this enum because it just expands to
166/// `NUMLIGHTS_1`, making them indistinguishable from each other.
167#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)]
168pub enum LightsNum {
169    /// 1 diffuse light.
170    #[doc(alias = "NUMLIGHTS_1")]
171    NumLights1 = 1,
172    /// 2 diffuse lights.
173    #[doc(alias = "NUMLIGHTS_2")]
174    NumLights2 = 2,
175    /// 3 diffuse lights.
176    #[doc(alias = "NUMLIGHTS_3")]
177    NumLights3 = 3,
178    /// 4 diffuse lights.
179    #[doc(alias = "NUMLIGHTS_4")]
180    NumLights4 = 4,
181    /// 5 diffuse lights.
182    #[doc(alias = "NUMLIGHTS_5")]
183    NumLights5 = 5,
184    /// 6 diffuse lights.
185    #[doc(alias = "NUMLIGHTS_6")]
186    NumLights6 = 6,
187    /// 7 diffuse lights.
188    #[doc(alias = "NUMLIGHTS_7")]
189    NumLights7 = 7,
190}
191
192impl LightsNum {
193    pub(crate) fn new(value: i32) -> Self {
194        match value {
195            1 => Self::NumLights1,
196            2 => Self::NumLights2,
197            3 => Self::NumLights3,
198            4 => Self::NumLights4,
199            5 => Self::NumLights5,
200            6 => Self::NumLights6,
201            7 => Self::NumLights7,
202            x => unreachable!(
203                "Oh, this shouldn't have had happen. Could you make a bug report? Value: {}",
204                x
205            ),
206        }
207    }
208}