fast3d_gbi/
defines.rs

1use bitflags::bitflags;
2use num_enum::TryFromPrimitive;
3use pigment64::color::Color;
4
5pub mod color_combiner;
6pub use color_combiner::*;
7pub mod render_mode;
8pub use render_mode::*;
9
10pub mod f3d;
11pub mod f3dex2;
12
13pub const G_MAXZ: u32 = 0x03ff;
14
15#[repr(C)]
16#[derive(Clone, Copy)]
17pub struct GfxWords {
18    pub w0: usize,
19    pub w1: usize,
20}
21
22#[repr(C)]
23#[derive(Clone, Copy)]
24pub union GfxCommand {
25    pub words: GfxWords,
26    force_structure_alignment: i64,
27}
28
29impl GfxCommand {
30    pub fn new(w0: usize, w1: usize) -> Self {
31        Self {
32            words: GfxWords { w0, w1 },
33        }
34    }
35
36    /// Reads a value from the command's first word.
37    pub fn w0(&self, position: u32, width: u32) -> usize {
38        unsafe { (self.words.w0 >> position) & ((1 << width) - 1) }
39    }
40
41    /// Reads a value from the command's second word.
42    pub fn w1(&self, position: u32, width: u32) -> usize {
43        unsafe { (self.words.w1 >> position) & ((1 << width) - 1) }
44    }
45}
46
47#[repr(C)]
48#[derive(Clone, Copy)]
49pub union Matrix {
50    pub m: [[u32; 4]; 4],
51    force_structure_alignment: i64,
52}
53
54#[repr(C)]
55#[derive(Clone, Copy)]
56pub union Vertex {
57    pub color: ColorVertex,
58    pub normal: NormalVertex,
59    force_structure_alignment: i64,
60}
61
62#[repr(C)]
63#[derive(Clone, Copy, Debug)]
64pub struct ColorVertex {
65    #[cfg(feature = "gbifloats")]
66    pub position: [f32; 3], // in object space
67    #[cfg(not(feature = "gbifloats"))]
68    pub position: [i16; 3], // in object space
69    flag: u16, // unused
70    pub texture_coords: [i16; 2],
71    pub color: Color,
72}
73
74impl ColorVertex {
75    pub const fn new(
76        #[cfg(feature = "gbifloats")] position: [f32; 3],
77        #[cfg(not(feature = "gbifloats"))] position: [i16; 3],
78        texture_coords: [i16; 2],
79        color: Color,
80    ) -> Self {
81        Self {
82            position,
83            flag: 0,
84            texture_coords,
85            color,
86        }
87    }
88}
89
90#[repr(C)]
91#[derive(Clone, Copy, Debug)]
92pub struct NormalVertex {
93    #[cfg(feature = "gbifloats")]
94    pub position: [f32; 3], // in object space
95    #[cfg(not(feature = "gbifloats"))]
96    pub position: [i16; 3], // in object space
97    flag: u16, // unused
98    pub texture_coords: [i16; 2],
99    pub normal: [i8; 3],
100    pub alpha: u8,
101}
102
103#[repr(C)]
104#[derive(Clone, Copy, Debug)]
105pub struct Viewport {
106    pub vscale: [i16; 4], // scale, 2 bits fraction
107    pub vtrans: [i16; 4], // translate, 2 bits fraction
108    _padding: [u8; 8],    // padding to 64-bit boundary
109}
110
111impl Viewport {
112    pub const fn new(vscale: [i16; 4], vtrans: [i16; 4]) -> Self {
113        Self {
114            vscale,
115            vtrans,
116            _padding: [0; 8],
117        }
118    }
119}
120
121#[repr(C)]
122#[derive(Clone, Copy)]
123pub struct RawLight {
124    pub words: [u32; 4],
125}
126
127#[repr(C)]
128#[derive(Clone, Copy)]
129pub union Light {
130    pub raw: RawLight,
131    pub pos: PosLight,
132    pub dir: DirLight,
133}
134
135#[repr(C)]
136#[derive(Clone, Copy)]
137pub struct DirLight {
138    pub col: [u8; 3], // diffuse light value (rgba)
139    pad1: i8,
140    pub color_copy: [u8; 3], // copy of diffuse light value (rgba)
141    pad2: i8,
142    pub dir: [i8; 3], // direction of light (normalized)
143    pad3: i8,
144}
145
146#[repr(C)]
147#[derive(Clone, Copy)]
148pub struct PosLight {
149    pub kc: u8,
150    pub col: [u8; 3],
151    pub kl: u8,
152    pub color_copy: [u8; 3],
153    pub pos: [i16; 2],
154    pub reserved1: u8,
155    pub kq: u8,
156    pub posz: i16,
157}
158
159impl Light {
160    pub const ZERO: Self = Self {
161        raw: RawLight {
162            words: [0, 0, 0, 0],
163        },
164    };
165}
166
167pub struct LookAt {
168    pub x: [f32; 3],
169    pub y: [f32; 3],
170}
171
172impl LookAt {
173    pub const fn new(x: [f32; 3], y: [f32; 3]) -> Self {
174        Self { x, y }
175    }
176}
177
178bitflags! {
179    pub struct OpCode: u8 {
180        const NOOP = 0x00;
181
182        const SET_COLORIMG = 0xff;
183        const SET_DEPTHIMG = 0xfe;
184        const SET_TEXIMG = 0xfd;
185        const SET_COMBINE = 0xfc;
186        const SET_ENVCOLOR = 0xfb;
187        const SET_PRIMCOLOR = 0xfa;
188        const SET_BLENDCOLOR = 0xf9;
189        const SET_FOGCOLOR = 0xf8;
190        const SET_FILLCOLOR = 0xf7;
191        const SET_TILE = 0xf5;
192        const SET_TILESIZE = 0xf2;
193        const SET_PRIMDEPTH = 0xee;
194        const SET_SCISSOR = 0xed;
195        const SET_CONVERT = 0xec;
196        const SET_KEYR = 0xeb;
197        const SET_KEYGB = 0xea;
198
199        const LOAD_BLOCK = 0xf3;
200        const LOAD_TILE = 0xf4;
201        const LOAD_TLUT = 0xf0;
202
203        const TEXRECT = 0xe4;
204        const TEXRECTFLIP = 0xe5;
205        const FILLRECT = 0xf6;
206
207        const RDPFULLSYNC = 0xe9;
208        const RDPTILESYNC = 0xe8;
209        const RDPPIPESYNC = 0xe7;
210        const RDPLOADSYNC = 0xe6;
211        const RDPSETOTHERMODE = 0xef;
212    }
213}
214
215#[allow(non_snake_case)]
216pub mod OtherModeH {
217    use bitflags::bitflags;
218
219    bitflags! {
220        pub struct Shift: u32 {
221            /// Unsupported.
222            const BLEND_MASK = 0x00000000;
223            const ALPHA_DITHER = 0x00000004;
224            const RGB_DITHER = 0x00000006;
225            const COMB_KEY = 0x00000008;
226            const TEXT_CONV = 0x00000009;
227            const TEXT_FILT = 0x0000000c;
228            const TEXT_LUT = 0x0000000e;
229            const TEXT_LOD = 0x00000010;
230            const TEXT_DETAIL = 0x00000011;
231            const TEXT_PERSP = 0x00000013;
232            const CYCLE_TYPE = 0x00000014;
233            /// Unsupported in HW 2.0
234            const COLOR_DITHER = 0x00000016;
235            const PIPELINE = 0x00000017;
236        }
237    }
238
239    impl Default for Shift {
240        fn default() -> Self {
241            Self::empty()
242        }
243    }
244}
245
246#[allow(non_snake_case)]
247pub mod OtherModeL {
248    use bitflags::bitflags;
249
250    bitflags! {
251        pub struct Shift: u32 {
252            const ALPHA_COMPARE = 0;
253            const DEPTH_SOURCE = 2;
254            const RENDER_MODE = 3;
255            const BLENDER = 16;
256        }
257    }
258
259    impl Default for Shift {
260        fn default() -> Self {
261            Self::empty()
262        }
263    }
264}
265
266bitflags! {
267    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
268    pub struct GeometryModes: u32 {
269        const ZBUFFER             = 0x00000001;
270        const SHADE               = 0x00000004;
271        const FOG                 = 0x00010000;
272        const LIGHTING            = 0x00020000;
273        const TEXTURE_GEN         = 0x00040000;
274        const TEXTURE_GEN_LINEAR  = 0x00080000;
275        const LOD                 = 0x00100000;
276        const CLIPPING            = 0x00800000;
277    }
278}
279
280bitflags! {
281    pub struct MoveWordIndex: u8 {
282        const MATRIX = 0x00; /* NOTE: also used by movemem */
283        const NUMLIGHT = 0x02;
284        const CLIP = 0x04;
285        const SEGMENT = 0x06;
286        const FOG = 0x08;
287        const LIGHTCOL = 0x0A;
288        const PERSPNORM = 0x0E;
289    }
290}
291
292bitflags! {
293    pub struct TextureTile: u8 {
294        const LOADTILE = 0x07;
295        const RENDERTILE = 0x00;
296    }
297}
298
299bitflags! {
300    pub struct TextureMask: u8 {
301        const NOMASK = 0x00;
302    }
303}
304
305bitflags! {
306    pub struct TextureShift: u8 {
307        const NOLOD = 0x00;
308    }
309}
310
311#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
312#[repr(u8)]
313pub enum DisplayListMode {
314    Display = 0,
315    Branch = 1,
316}
317
318impl Default for DisplayListMode {
319    fn default() -> Self {
320        Self::Display
321    }
322}
323
324#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
325#[repr(u8)]
326pub enum TextureFilter {
327    Point = 0,
328    Average = 3,
329    Bilerp = 2,
330}
331
332impl Default for TextureFilter {
333    fn default() -> Self {
334        Self::Point
335    }
336}
337
338impl TextureFilter {
339    pub const fn raw_gbi_value(&self) -> u32 {
340        const G_MDSFT_TEXTFILT: u32 = 12;
341        match self {
342            Self::Point => 0 << G_MDSFT_TEXTFILT,
343            Self::Average => 3 << G_MDSFT_TEXTFILT,
344            Self::Bilerp => 2 << G_MDSFT_TEXTFILT,
345        }
346    }
347}
348
349#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
350#[repr(u8)]
351pub enum TextureLUT {
352    None = 0,
353    Rgba16 = 2,
354    Ia16 = 3,
355}
356
357impl Default for TextureLUT {
358    fn default() -> Self {
359        Self::None
360    }
361}
362
363impl TextureLUT {
364    pub const fn raw_gbi_value(&self) -> u32 {
365        const G_MDSFT_TEXTLUT: u32 = 14;
366        match self {
367            Self::None => 0,
368            Self::Rgba16 => 2 << G_MDSFT_TEXTLUT,
369            Self::Ia16 => 3 << G_MDSFT_TEXTLUT,
370        }
371    }
372}
373
374#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
375#[repr(u8)]
376pub enum TextureLOD {
377    Tile = 0,
378    Lod = 1,
379}
380
381impl Default for TextureLOD {
382    fn default() -> Self {
383        Self::Tile
384    }
385}
386
387impl TextureLOD {
388    pub const fn raw_gbi_value(&self) -> u32 {
389        const G_MDSFT_TEXTLOD: u32 = 16;
390        match self {
391            Self::Tile => 0,
392            Self::Lod => 1 << G_MDSFT_TEXTLOD,
393        }
394    }
395}
396
397#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
398#[repr(u8)]
399pub enum TextureDetail {
400    Clamp = 0,
401    Sharpen = 1,
402    Detail = 2,
403}
404
405impl Default for TextureDetail {
406    fn default() -> Self {
407        Self::Clamp
408    }
409}
410
411impl TextureDetail {
412    pub const fn raw_gbi_value(&self) -> u32 {
413        const G_MDSFT_TEXTDETAIL: u32 = 17;
414        match self {
415            Self::Clamp => 0,
416            Self::Sharpen => 1 << G_MDSFT_TEXTDETAIL,
417            Self::Detail => 2 << G_MDSFT_TEXTDETAIL,
418        }
419    }
420}
421
422#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
423#[repr(u8)]
424pub enum TextureConvert {
425    Conv = 0,
426    FiltConv = 5,
427    Filt = 6,
428}
429
430impl Default for TextureConvert {
431    fn default() -> Self {
432        Self::Conv
433    }
434}
435
436impl TextureConvert {
437    pub const fn raw_gbi_value(&self) -> u32 {
438        const G_MDSFT_TEXTCONV: u32 = 9;
439        match self {
440            Self::Conv => 0 << G_MDSFT_TEXTCONV,
441            Self::FiltConv => 5 << G_MDSFT_TEXTCONV,
442            Self::Filt => 6 << G_MDSFT_TEXTCONV,
443        }
444    }
445}
446
447#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
448#[repr(u8)]
449pub enum ColorDither {
450    MagicSq = 0,
451    Bayer = 1,
452    Noise = 2,
453    Disable = 3,
454}
455
456impl Default for ColorDither {
457    fn default() -> Self {
458        Self::Disable
459    }
460}
461
462impl ColorDither {
463    #[cfg(not(feature = "hardware_version_1"))]
464    pub const fn raw_gbi_value(&self) -> u32 {
465        const G_MDSFT_RGBDITHER: u32 = 19;
466        match self {
467            Self::MagicSq => 0 << G_MDSFT_RGBDITHER,
468            Self::Bayer => 1 << G_MDSFT_RGBDITHER,
469            Self::Noise => 2 << G_MDSFT_RGBDITHER,
470            Self::Disable => 3 << G_MDSFT_RGBDITHER,
471        }
472    }
473}
474
475#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
476#[repr(u8)]
477pub enum ImageFormat {
478    Rgba = 0,
479    Yuv = 1,
480    Ci = 2,
481    Ia = 3,
482    I = 4,
483}
484
485#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
486#[repr(u8)]
487pub enum ComponentSize {
488    Bits4 = 0,
489    Bits8 = 1,
490    Bits16 = 2,
491    Bits32 = 3,
492    DD = 5,
493}
494
495impl Default for ComponentSize {
496    fn default() -> Self {
497        Self::Bits4
498    }
499}
500
501#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
502#[repr(u8)]
503pub enum CycleType {
504    OneCycle = 0,
505    TwoCycle = 1,
506    Copy = 2,
507    Fill = 3,
508}
509
510impl Default for CycleType {
511    fn default() -> Self {
512        Self::OneCycle
513    }
514}
515
516impl CycleType {
517    pub const fn raw_gbi_value(&self) -> u32 {
518        const G_MDSFT_CYCLETYPE: u32 = 20;
519        match self {
520            CycleType::OneCycle => 0 << G_MDSFT_CYCLETYPE,
521            CycleType::TwoCycle => 1 << G_MDSFT_CYCLETYPE,
522            CycleType::Copy => 2 << G_MDSFT_CYCLETYPE,
523            CycleType::Fill => 3 << G_MDSFT_CYCLETYPE,
524        }
525    }
526}
527
528#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
529#[repr(u8)]
530pub enum PipelineMode {
531    OnePrimitive = 1,
532    NPrimitive = 0,
533}
534
535impl Default for PipelineMode {
536    fn default() -> Self {
537        Self::NPrimitive
538    }
539}
540
541impl PipelineMode {
542    pub const fn raw_gbi_value(&self) -> u32 {
543        const G_MDSFT_PIPELINE: u32 = 23;
544        match self {
545            PipelineMode::OnePrimitive => 1 << G_MDSFT_PIPELINE,
546            PipelineMode::NPrimitive => 0 << G_MDSFT_PIPELINE,
547        }
548    }
549}
550
551#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
552#[repr(u8)]
553#[allow(clippy::enum_variant_names)]
554pub enum ScissorMode {
555    NonInterlace = 0,
556    OddInterlace = 3,
557    EvenInterlace = 2,
558}
559
560impl Default for ScissorMode {
561    fn default() -> Self {
562        Self::NonInterlace
563    }
564}
565
566#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, TryFromPrimitive)]
567#[repr(u8)]
568pub enum AlphaCompare {
569    None = 0,
570    Threshold = 1,
571    Dither = 3,
572}
573
574impl Default for AlphaCompare {
575    fn default() -> Self {
576        Self::None
577    }
578}
579
580impl AlphaCompare {
581    pub const fn raw_gbi_value(&self) -> u32 {
582        const G_MDSFT_ALPHACOMPARE: u32 = 0;
583        match self {
584            AlphaCompare::None => 0 << G_MDSFT_ALPHACOMPARE,
585            AlphaCompare::Threshold => 1 << G_MDSFT_ALPHACOMPARE,
586            AlphaCompare::Dither => 3 << G_MDSFT_ALPHACOMPARE,
587        }
588    }
589}
590
591#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
592#[repr(u8)]
593pub enum WrapMode {
594    Clamp,
595    Repeat,
596    MirrorRepeat,
597}
598
599impl Default for WrapMode {
600    fn default() -> Self {
601        Self::Repeat
602    }
603}
604
605impl From<u8> for WrapMode {
606    fn from(v: u8) -> Self {
607        let mirror = v & 0x1 != 0;
608        let clamp = v & 0x2 != 0;
609
610        if clamp {
611            WrapMode::Clamp
612        } else if mirror {
613            WrapMode::MirrorRepeat
614        } else {
615            WrapMode::Repeat
616        }
617    }
618}