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}