1use crate::gbi::macros::gbi_command;
2use crate::gbi::utils::get_cmd;
3use crate::gbi::{GBICommandParams, GBICommandRegistry, GBIResult};
4use fast3d_gbi::defines::{CombineParams, OpCode, WrapMode};
5
6use crate::models::texture::TextureImageState;
7
8use crate::rdp::SCREEN_HEIGHT;
9use crate::rsp::RSP;
10
11pub struct Common;
12impl Common {
13 pub fn setup(gbi: &mut GBICommandRegistry, _rsp: &mut RSP) {
14 gbi.register(OpCode::NOOP.bits(), RDPNoOp);
15 gbi.register(OpCode::TEXRECT.bits(), RDPTextureRectangle);
16 gbi.register(OpCode::TEXRECTFLIP.bits(), RDPTextureRectangle);
17 gbi.register(OpCode::FILLRECT.bits(), RDPFillRectangle);
18 gbi.register(OpCode::SET_COLORIMG.bits(), RDPSetColorImage);
19 gbi.register(OpCode::SET_DEPTHIMG.bits(), RDPSetDepthImage);
20 gbi.register(OpCode::SET_TEXIMG.bits(), RDPSetTextureImage);
21 gbi.register(OpCode::SET_COMBINE.bits(), RDPSetCombine);
22 gbi.register(OpCode::SET_TILE.bits(), RDPSetTile);
23 gbi.register(OpCode::SET_TILESIZE.bits(), RDPSetTileSize);
24 gbi.register(OpCode::SET_ENVCOLOR.bits(), RDPSetEnvColor);
25 gbi.register(OpCode::SET_PRIMCOLOR.bits(), RDPSetPrimColor);
26 gbi.register(OpCode::SET_BLENDCOLOR.bits(), RDPSetBlendColor);
27 gbi.register(OpCode::SET_FOGCOLOR.bits(), RDPSetFogColor);
28 gbi.register(OpCode::SET_FILLCOLOR.bits(), RDPSetFillColor);
29 gbi.register(OpCode::SET_SCISSOR.bits(), RDPSetScissor);
31 gbi.register(OpCode::SET_CONVERT.bits(), RDPSetConvert);
32 gbi.register(OpCode::SET_KEYR.bits(), RDPSetKeyR);
33 gbi.register(OpCode::SET_KEYGB.bits(), RDPSetKeyGB);
34 gbi.register(OpCode::LOAD_TILE.bits(), RDPLoadTile);
35 gbi.register(OpCode::LOAD_BLOCK.bits(), RDPLoadBlock);
36 gbi.register(OpCode::LOAD_TLUT.bits(), RDPLoadTLUT);
37 gbi.register(OpCode::RDPLOADSYNC.bits(), RDPLoadSync);
38 gbi.register(OpCode::RDPPIPESYNC.bits(), RDPPipeSync);
39 gbi.register(OpCode::RDPTILESYNC.bits(), RDPTileSync);
40 gbi.register(OpCode::RDPFULLSYNC.bits(), RDPFullSync);
41 gbi.register(OpCode::RDPSETOTHERMODE.bits(), RDPSetOtherMode);
42 }
43}
44
45gbi_command!(RDPNoOp, |_| { GBIResult::Continue });
46gbi_command!(RDPLoadSync, |_| { GBIResult::Continue });
47gbi_command!(RDPPipeSync, |_| { GBIResult::Continue });
48gbi_command!(RDPTileSync, |_| { GBIResult::Continue });
49gbi_command!(RDPFullSync, |_| { GBIResult::Continue });
50
51gbi_command!(RDPSetColorImage, |params: &mut GBICommandParams| {
52 let w0 = unsafe { (*(*params.command)).words.w0 };
53 let w1 = unsafe { (*(*params.command)).words.w1 };
54
55 let _format = get_cmd(w0, 21, 3);
56 let _size = get_cmd(w0, 19, 2);
57 let _width = get_cmd(w0, 0, 12) + 1;
58
59 params.rdp.color_image = params.rsp.get_segment(w1);
60 GBIResult::Continue
61});
62
63gbi_command!(RDPSetDepthImage, |params: &mut GBICommandParams| {
64 let w1 = unsafe { (*(*params.command)).words.w1 };
65
66 params.rdp.depth_image = params.rsp.get_segment(w1);
67 GBIResult::Continue
68});
69
70gbi_command!(RDPSetTextureImage, |params: &mut GBICommandParams| {
71 let w0 = unsafe { (*(*params.command)).words.w0 };
72 let w1 = unsafe { (*(*params.command)).words.w1 };
73
74 let format = get_cmd(w0, 21, 3) as u8;
75 let size = get_cmd(w0, 19, 2) as u8;
76 let width = get_cmd(w0, 0, 12) as u16 + 1;
77 let address = params.rsp.get_segment(w1);
78
79 params.rdp.texture_image_state = TextureImageState {
80 format,
81 size,
82 width,
83 address,
84 };
85
86 GBIResult::Continue
87});
88
89gbi_command!(RDPSetCombine, |params: &mut GBICommandParams| {
90 let w0 = unsafe { (*(*params.command)).words.w0 };
91 let w1 = unsafe { (*(*params.command)).words.w1 };
92 params.rdp.set_combine(CombineParams::decode(w0, w1));
93
94 GBIResult::Continue
95});
96
97gbi_command!(RDPSetTile, |params: &mut GBICommandParams| {
98 let w0 = unsafe { (*(*params.command)).words.w0 };
99 let w1 = unsafe { (*(*params.command)).words.w1 };
100
101 let format = get_cmd(w0, 21, 3) as u8;
102 let size = get_cmd(w0, 19, 2) as u8;
103 let line = get_cmd(w0, 9, 9) as u16;
104 let tmem = get_cmd(w0, 0, 9) as u16;
105 let tile = get_cmd(w1, 24, 3) as u8;
106 let palette = get_cmd(w1, 20, 4) as u8;
107 let cm_t: WrapMode = ((get_cmd(w1, 18, 2) & 0x3) as u8).into();
108 let mask_t: u8 = get_cmd(w1, 14, 4) as u8;
109 let shift_t: u8 = get_cmd(w1, 10, 4) as u8;
110 let cm_s: WrapMode = ((get_cmd(w1, 8, 2) & 0x3) as u8).into();
111 let mask_s: u8 = get_cmd(w1, 4, 4) as u8;
112 let shift_s: u8 = get_cmd(w1, 0, 4) as u8;
113
114 params.rdp.set_tile(
115 tile, format, size, line, tmem, palette, cm_t, cm_s, mask_t, mask_s, shift_t, shift_s,
116 );
117
118 GBIResult::Continue
119});
120
121gbi_command!(RDPSetTileSize, |params: &mut GBICommandParams| {
122 let w0 = unsafe { (*(*params.command)).words.w0 };
123 let w1 = unsafe { (*(*params.command)).words.w1 };
124
125 let tile = get_cmd(w1, 24, 3) as u8;
126 let uls = get_cmd(w0, 12, 12) as u16;
127 let ult = get_cmd(w0, 0, 12) as u16;
128 let lrs = get_cmd(w1, 12, 12) as u16;
129 let lrt = get_cmd(w1, 0, 12) as u16;
130
131 params.rdp.set_tile_size(tile, ult, uls, lrt, lrs);
132
133 GBIResult::Continue
134});
135
136gbi_command!(RDPLoadTile, |params: &mut GBICommandParams| {
137 let w0 = unsafe { (*(*params.command)).words.w0 };
138 let w1 = unsafe { (*(*params.command)).words.w1 };
139
140 let tile = get_cmd(w1, 24, 3) as u8;
141 let uls = get_cmd(w0, 12, 12) as u16;
142 let ult = get_cmd(w0, 0, 12) as u16;
143 let lrs = get_cmd(w1, 12, 12) as u16;
144 let lrt = get_cmd(w1, 0, 12) as u16;
145
146 params.rdp.load_tile(tile, ult, uls, lrt, lrs);
147
148 GBIResult::Continue
149});
150
151gbi_command!(RDPLoadBlock, |params: &mut GBICommandParams| {
152 let w0 = unsafe { (*(*params.command)).words.w0 };
153 let w1 = unsafe { (*(*params.command)).words.w1 };
154
155 let tile = get_cmd(w1, 24, 3) as u8;
156 let uls = get_cmd(w0, 12, 12) as u16;
157 let ult = get_cmd(w0, 0, 12) as u16;
158 let texels = get_cmd(w1, 12, 12) as u16;
159 let dxt = get_cmd(w1, 0, 12) as u16;
160
161 params.rdp.load_block(tile, ult, uls, texels, dxt);
162
163 GBIResult::Continue
164});
165
166gbi_command!(RDPLoadTLUT, |params: &mut GBICommandParams| {
167 let w1 = unsafe { (*(*params.command)).words.w1 };
168
169 let tile = get_cmd(w1, 24, 3) as u8;
170 let high_index = get_cmd(w1, 14, 10) as u16;
171
172 params.rdp.load_tlut(tile, high_index);
173
174 GBIResult::Continue
175});
176
177gbi_command!(RDPSetEnvColor, |params: &mut GBICommandParams| {
178 let w1 = unsafe { (*(*params.command)).words.w1 };
179 params.rdp.set_env_color(w1);
180
181 GBIResult::Continue
182});
183
184gbi_command!(RDPSetPrimColor, |params: &mut GBICommandParams| {
185 let w0 = unsafe { (*(*params.command)).words.w0 };
186 let w1 = unsafe { (*(*params.command)).words.w1 };
187
188 let lod_frac = get_cmd(w0, 0, 8) as u8;
189 let lod_min = get_cmd(w0, 8, 5) as u8;
190 params.rdp.set_prim_color(lod_frac, lod_min, w1);
191
192 GBIResult::Continue
193});
194
195gbi_command!(RDPSetBlendColor, |params: &mut GBICommandParams| {
196 let w1 = unsafe { (*(*params.command)).words.w1 };
197 params.rdp.set_blend_color(w1);
198
199 GBIResult::Continue
200});
201
202gbi_command!(RDPSetFogColor, |params: &mut GBICommandParams| {
203 let w1 = unsafe { (*(*params.command)).words.w1 };
204 params.rdp.set_fog_color(w1);
205
206 GBIResult::Continue
207});
208
209gbi_command!(RDPSetFillColor, |params: &mut GBICommandParams| {
210 let w1 = unsafe { (*(*params.command)).words.w1 };
211 params.rdp.set_fill_color(w1);
212
213 GBIResult::Continue
214});
215
216gbi_command!(RDPSetOtherMode, |params: &mut GBICommandParams| {
217 let w0 = unsafe { (*(*params.command)).words.w0 };
218 let w1 = unsafe { (*(*params.command)).words.w1 };
219
220 let high = get_cmd(w0, 0, 24);
221 let low = w1;
222 params.rdp.set_other_mode(high as u32, low as u32);
223
224 GBIResult::Continue
225});
226
227gbi_command!(RDPSetScissor, |params: &mut GBICommandParams| {
228 let w0 = unsafe { (*(*params.command)).words.w0 };
229 let w1 = unsafe { (*(*params.command)).words.w1 };
230
231 let _mode = get_cmd(w1, 24, 2);
232 let ulx = get_cmd(w0, 12, 12);
233 let uly = get_cmd(w0, 0, 12);
234 let lrx = get_cmd(w1, 12, 12);
235 let lry = get_cmd(w1, 0, 12);
236
237 let x = ulx as f32 / 4.0 * params.rdp.scaled_x();
238 let y = (SCREEN_HEIGHT - lry as f32 / 4.0) * params.rdp.scaled_y();
239 let width = (lrx as f32 - ulx as f32) / 4.0 * params.rdp.scaled_x();
240 let height = (lry as f32 - uly as f32) / 4.0 * params.rdp.scaled_y();
241
242 params.rdp.scissor.x = x as u16;
243 params.rdp.scissor.y = y as u16;
244 params.rdp.scissor.width = width as u16;
245 params.rdp.scissor.height = height as u16;
246
247 params.rdp.shader_config_changed = true;
248 GBIResult::Continue
249});
250
251gbi_command!(RDPSetConvert, |params: &mut GBICommandParams| {
252 let w0 = unsafe { (*(*params.command)).words.w0 };
253 let w1 = unsafe { (*(*params.command)).words.w1 };
254
255 let k0 = get_cmd(w0, 13, 9);
256 let k1 = get_cmd(w0, 4, 9);
257 let k2 = (get_cmd(w0, 0, 4) << 5) | get_cmd(w1, 27, 5);
258 let k3 = get_cmd(w1, 18, 9);
259 let k4 = get_cmd(w1, 9, 9);
260 let k5 = get_cmd(w1, 0, 9);
261
262 params.rdp.set_convert(
263 k0 as i32, k1 as i32, k2 as i32, k3 as i32, k4 as i32, k5 as i32,
264 );
265
266 GBIResult::Continue
267});
268
269gbi_command!(RDPSetKeyR, |params: &mut GBICommandParams| {
270 let w1 = unsafe { (*(*params.command)).words.w1 };
271
272 let cr = get_cmd(w1, 8, 8);
273 let sr = get_cmd(w1, 0, 8);
274 let wr = get_cmd(w1, 16, 2);
275
276 params.rdp.set_key_r(cr as u32, sr as u32, wr as u32);
277
278 GBIResult::Continue
279});
280
281gbi_command!(RDPSetKeyGB, |params: &mut GBICommandParams| {
282 let w0 = unsafe { (*(*params.command)).words.w0 };
283 let w1 = unsafe { (*(*params.command)).words.w1 };
284
285 let cg = get_cmd(w1, 24, 8);
286 let sg = get_cmd(w1, 16, 8);
287 let wg = get_cmd(w0, 12, 12);
288 let cb = get_cmd(w1, 8, 8);
289 let sb = get_cmd(w1, 0, 8);
290 let wb = get_cmd(w0, 0, 12);
291
292 params.rdp.set_key_gb(
293 cg as u32, sg as u32, wg as u32, cb as u32, sb as u32, wb as u32,
294 );
295
296 GBIResult::Continue
297});
298
299gbi_command!(RDPTextureRectangle, |params: &mut GBICommandParams| {
300 let w0 = unsafe { (*(*params.command)).words.w0 };
301 let w1 = unsafe { (*(*params.command)).words.w1 };
302
303 let opcode = (w0 >> 24) as u8;
304
305 let lrx = get_cmd(w0, 12, 12);
306 let lry = get_cmd(w0, 0, 12);
307 let tile = get_cmd(w1, 24, 3);
308 let ulx = get_cmd(w1, 12, 12);
309 let uly = get_cmd(w1, 0, 12);
310
311 unsafe {
312 *params.command = (*params.command).add(1);
313 }
314 let w1 = unsafe { (*(*params.command)).words.w1 };
315
316 let uls = get_cmd(w1, 16, 16);
317 let ult = get_cmd(w1, 0, 16);
318
319 unsafe {
320 *params.command = (*params.command).add(1);
321 }
322 let w1 = unsafe { (*(*params.command)).words.w1 };
323
324 let dsdx = get_cmd(w1, 16, 16);
325 let dtdy = get_cmd(w1, 0, 16);
326
327 params.rdp.draw_texture_rectangle(
328 params.rsp,
329 params.output,
330 ulx as i32,
331 uly as i32,
332 lrx as i32,
333 lry as i32,
334 tile as u8,
335 uls as i16,
336 ult as i16,
337 dsdx as i16,
338 dtdy as i16,
339 opcode == OpCode::TEXRECTFLIP.bits(),
340 );
341
342 GBIResult::Continue
343});
344
345gbi_command!(RDPFillRectangle, |params: &mut GBICommandParams| {
346 let w0 = unsafe { (*(*params.command)).words.w0 };
347 let w1 = unsafe { (*(*params.command)).words.w1 };
348
349 let ulx = get_cmd(w1, 12, 12);
350 let uly = get_cmd(w1, 0, 12);
351 let lrx = get_cmd(w0, 12, 12);
352 let lry = get_cmd(w0, 0, 12);
353
354 params.rdp.fill_rect(
355 params.rsp,
356 params.output,
357 ulx as i32,
358 uly as i32,
359 lrx as i32,
360 lry as i32,
361 );
362
363 GBIResult::Continue
364});