fast3d/
rcp.rs

1use super::{output::RenderData, rdp::RDP, rsp::RSP};
2use crate::gbi::{GBICommandParams, GBICommandRegistry, GBIResult};
3use fast3d_gbi::defines::GfxCommand;
4
5pub struct RCP {
6    gbi: GBICommandRegistry,
7    pub rdp: RDP,
8    pub rsp: RSP,
9}
10
11impl Default for RCP {
12    fn default() -> Self {
13        Self::new()
14    }
15}
16
17impl RCP {
18    pub fn new() -> Self {
19        let mut gbi = GBICommandRegistry::default();
20        let mut rsp = RSP::default();
21        gbi.setup(&mut rsp);
22
23        RCP {
24            gbi,
25            rdp: RDP::default(),
26            rsp,
27        }
28    }
29
30    pub fn reset(&mut self) {
31        self.rdp.reset();
32        self.rsp.reset();
33    }
34
35    /// Processes a render list. Takes in a pointer to the start of the
36    /// render list and process until it hits a final `G_ENDDL`.
37    /// Returns a `RenderData` struct containing graphics data that
38    /// can be used to render.
39    pub fn process_dl(&mut self, commands: usize, output: &mut RenderData) {
40        self.reset();
41        self.run_dl(output, commands);
42        self.rdp.flush(output);
43    }
44
45    fn run_dl(&mut self, output: &mut RenderData, commands: usize) {
46        let mut command = commands as *mut GfxCommand;
47
48        loop {
49            let opcode = (unsafe { (*command).words.w0 } >> 24) as u8;
50            if let Some(handler) = self.gbi.handler(&opcode) {
51                let handler_input = &mut GBICommandParams {
52                    rdp: &mut self.rdp,
53                    rsp: &mut self.rsp,
54                    output,
55                    command: &mut command,
56                };
57                match handler(handler_input) {
58                    GBIResult::Recurse(new_command) => self.run_dl(output, new_command),
59                    GBIResult::Return => return,
60                    GBIResult::Continue => {}
61                }
62            } else {
63                log::trace!("Unknown GBI command: {:#x}", opcode);
64            }
65
66            unsafe { command = command.add(1) };
67        }
68    }
69}