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 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}