gfxd_rs/
lib.rs

1/* SPDX-FileCopyrightText: © 2025 Decompollaborate */
2/* SPDX-License-Identifier: MIT OR Apache-2.0 */
3
4// TODO: Use #![doc = include_str!("../README.md")] when the MSRV is 1.54+
5//! A safe Rust wrapper for [glankk](https://github.com/glankk)'s C library
6//! [`libgfxd`](https://github.com/glankk/libgfxd), the defacto N64 display
7//! list disassembler library.
8//!
9//! This crate uses the [`gfxd-sys`](https://crates.io/crates/gfxd-sys) crate,
10//! which exposes Raw FFI bindings for `libgfxd`, meaning this crate requires a
11//! C compiler.
12//!
13//! ## Example usage
14//!
15//! The [`Disassembler`] is the entrypoint for using this crate.
16//!
17//! ```rust
18//! use gfxd_rs::{Customizer, Disassembler, MacroPrinter, Microcode, Printer};
19//!
20//! // F3DEX data
21//! static INPUT: [u8; 0x60] = [
22//!     0xE7, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23//!     0xFC, 0x12, 0x7E, 0x03, 0xFF, 0xFF, 0xFD, 0xF8,
24//!     0xB9, 0x00, 0x03, 0x1D, 0xC8, 0x11, 0x20, 0x78,
25//!     0xB6, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x00, 0x00,
26//!     0xB7, 0x00, 0x00, 0x00, 0x00, 0x01, 0x20, 0x00,
27//!     0xFA, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
28//!     0x04, 0x00, 0x30, 0xBF, 0x00, 0x00, 0x02, 0xE0,
29//!     0xB1, 0x00, 0x02, 0x04, 0x00, 0x02, 0x06, 0x04,
30//!     0xB1, 0x08, 0x0A, 0x0C, 0x00, 0x0A, 0x0E, 0x0C,
31//!     0xB1, 0x0A, 0x10, 0x12, 0x00, 0x0A, 0x12, 0x0E,
32//!     0xB1, 0x14, 0x02, 0x00, 0x00, 0x14, 0x00, 0x16,
33//!     0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
34//! ];
35//! static OUTPUT: &str = "\
36//! {
37//!     gsDPPipeSync(),
38//!     gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, 0, 0, 0, 1, COMBINED, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED),
39//!     gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2),
40//!     gsSPClearGeometryMode(G_LIGHTING | G_TEXTURE_GEN | G_TEXTURE_GEN_LINEAR),
41//!     gsSPSetGeometryMode(G_CULL_BACK | G_FOG),
42//!     gsDPSetPrimColor(0, 0, 0xFF, 0xFF, 0xFF, 0xFF),
43//!     gsSPVertex(0x000002E0, 12, 0),
44//!     gsSP2Triangles(0, 1, 2, 0, 1, 3, 2, 0),
45//!     gsSP2Triangles(4, 5, 6, 0, 5, 7, 6, 0),
46//!     gsSP1Quadrangle(5, 8, 9, 7, 0),
47//!     gsSP1Quadrangle(10, 1, 0, 11, 0),
48//!     gsSPEndDisplayList(),
49//! }
50//! ";
51//!
52//! // Customize the generated output.
53//! let mut customizer = Customizer::new();
54//!
55//! // Override the default macro handler to make the output prettier.
56//! let mut macro_fn = |printer: &mut MacroPrinter, _info: &mut _| {
57//!     // Print 4 spaces before each macro, and a comma and newline after each macro.
58//!     printer.write_str("    ");
59//!     // Execute the default macro handler.
60//!     let ret = printer.macro_dflt();
61//!     printer.write_str(",\n");
62//!     ret
63//! };
64//! customizer.macro_fn(&mut macro_fn);
65//!
66//! // Print an opening and closing brace around the disassembled data.
67//! let mut before = |printer: &mut Printer| {
68//!     printer.write_str("{\n");
69//! };
70//! let mut after = |printer: &mut Printer| {
71//!     printer.write_str("}\n");
72//! };
73//! customizer.before_after_execution_callback(&mut before, &mut after);
74//!
75//! // Select F3DEX as the target microcode and pass a data buffer, executing
76//! // until either the end of input or encountering an invalid command.
77//! let out = Disassembler::new().disassemble(&INPUT, Microcode::F3dex, &mut customizer);
78//!
79//! // Check the disassembly is formatted as we expect.
80//! assert_eq!(OUTPUT, out);
81//! ```
82
83#![cfg_attr(not(feature = "std"), no_std)]
84#![deny(improper_ctypes)]
85#![warn(missing_docs)]
86// TODO: enable in MSRV 1.52+
87// #![deny(unsafe_op_in_unsafe_fn)]
88// TODO: Change some `allow`ed clippy warnings into `expect`ed ones in MSRV 1.81+.
89#![warn(clippy::missing_const_for_fn)]
90#![warn(clippy::must_use_candidate)]
91#![allow(clippy::cast_sign_loss)]
92#![warn(clippy::semicolon_if_nothing_returned)]
93#![warn(clippy::cast_possible_truncation)]
94#![allow(clippy::as_underscore)]
95#![allow(clippy::expect_used)]
96#![warn(clippy::unwrap_used)]
97#![allow(clippy::shadow_reuse)]
98#![warn(clippy::str_to_string)]
99#![warn(clippy::shadow_unrelated)]
100#![warn(clippy::unused_trait_names)]
101
102extern crate alloc;
103
104pub(crate) mod arg_type;
105pub(crate) mod customizer;
106pub(crate) mod disassembler;
107pub(crate) mod lib_data;
108pub(crate) mod macro_id;
109pub(crate) mod macro_info;
110pub(crate) mod microcode;
111pub(crate) mod new_types;
112pub(crate) mod printer;
113pub(crate) mod utils;
114
115pub use arg_type::ArgType;
116pub use customizer::{Customizer, DoDefaultOutput, MacroFnRet};
117pub use disassembler::Disassembler;
118pub use macro_id::MacroId;
119pub use macro_info::{ArgValue, MacroInfo};
120pub use microcode::Microcode;
121pub use new_types::{Address, LightsNum, LookatCount, TexFmt, TexSiz, TlutCount};
122pub use printer::{MacroPrinter, Printer};