Skip to content

Commit 7b2d554

Browse files
committed
Implement missing 3d tests
1 parent ad623db commit 7b2d554

File tree

2 files changed

+151
-47
lines changed

2 files changed

+151
-47
lines changed

src/core/graphics/gpu_3d/registers_3d.rs

Lines changed: 143 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use std::mem;
1414
#[derive(Copy, Clone, FromBits)]
1515
pub struct GxStat {
1616
box_pos_vec_test_busy: bool,
17-
box_test_result: u1,
17+
box_test_result: bool,
1818
not_used: u6,
1919
pos_vec_mtx_stack_lvl: u5,
2020
proj_mtx_stack_lvl: u1,
@@ -231,24 +231,24 @@ pub struct Vertex {
231231
pub color: u32,
232232
}
233233

234-
fn intersect(v1: &Vertex, v2: &Vertex, val1: i32, val2: i32) -> Vertex {
235-
let d1 = val1 as i64 + v1.coords[3] as i64;
236-
let d2 = val2 as i64 + v2.coords[3] as i64;
234+
fn intersect(v1: &Vectori32<4>, v2: &Vectori32<4>, val1: i32, val2: i32) -> Vectori32<4> {
235+
let d1 = val1 as i64 + v1[3] as i64;
236+
let d2 = val2 as i64 + v2[3] as i64;
237237
if d2 == d1 {
238238
return *v1;
239239
}
240240

241-
let mut vertex = Vertex::default();
241+
let mut vertex = Vectori32::default();
242242
for i in 0..4 {
243-
vertex.coords[i] = v1.coords[i] + ((v2.coords[i] - v1.coords[i]) as i64 * -d1 / (d2 - d1)) as i32;
243+
vertex[i] = v1[i] + ((v2[i] - v1[i]) as i64 * -d1 / (d2 - d1)) as i32;
244244
}
245245
vertex
246246
}
247247

248-
fn clip_polygon(unclipped: &[Vertex; 4], clipped: &mut [Vertex; 10], size: &mut usize) -> bool {
248+
fn clip_polygon(unclipped: &[Vectori32<4>; 4], clipped: &mut [Vectori32<4>; 10], size: &mut usize) -> bool {
249249
let mut clip = false;
250250

251-
let mut vertices = [Vertex::default(); 10];
251+
let mut vertices = [Vectori32::<4>::default(); 10];
252252
vertices[..4].copy_from_slice(unclipped);
253253

254254
for i in 0..6 {
@@ -260,25 +260,25 @@ fn clip_polygon(unclipped: &[Vertex; 4], clipped: &mut [Vertex; 10], size: &mut
260260
let previous = &vertices[(j.wrapping_sub(1).wrapping_add(old_size)) % old_size];
261261

262262
let (current_val, previous_val) = match i {
263-
0 => (current.coords[0], previous.coords[0]),
264-
1 => (-current.coords[0], -previous.coords[0]),
265-
2 => (current.coords[1], previous.coords[1]),
266-
3 => (-current.coords[1], -previous.coords[1]),
267-
4 => (current.coords[2], previous.coords[2]),
268-
5 => (-current.coords[2], -previous.coords[2]),
263+
0 => (current[0], previous[0]),
264+
1 => (-current[0], -previous[0]),
265+
2 => (current[1], previous[1]),
266+
3 => (-current[1], -previous[1]),
267+
4 => (current[2], previous[2]),
268+
5 => (-current[2], -previous[2]),
269269
_ => unsafe { unreachable_unchecked() },
270270
};
271271

272-
if current_val >= -current.coords[3] {
273-
if previous_val < -previous.coords[3] {
272+
if current_val >= -current[3] {
273+
if previous_val < -previous[3] {
274274
clipped[*size] = intersect(current, previous, current_val, previous_val);
275275
*size += 1;
276276
clip = true;
277277
}
278278

279279
clipped[*size] = *current;
280280
*size += 1;
281-
} else if previous_val >= -previous.coords[3] {
281+
} else if previous_val >= -previous[3] {
282282
clipped[*size] = intersect(current, previous, current_val, previous_val);
283283
*size += 1;
284284
clip = true;
@@ -392,8 +392,8 @@ pub struct Polygons {
392392
pub struct Gpu3DRegisters {
393393
cmd_fifo: VecDeque<Entry>,
394394
cmd_pipe_size: u8,
395-
mtx_queue: u32,
396395
test_queue: u32,
396+
mtx_queue: u32,
397397

398398
cmd_fifo_param_count: u32,
399399

@@ -437,8 +437,8 @@ pub struct Gpu3DRegisters {
437437

438438
pub gx_stat: GxStat,
439439
gx_fifo: u32,
440-
pos_result: [i32; 4],
441-
vec_result: [i16; 3],
440+
pos_result: Vectori32<4>,
441+
vec_result: Vectori16<3>,
442442
}
443443

444444
impl Gpu3DRegisters {
@@ -547,15 +547,9 @@ impl Gpu3DRegisters {
547547
0x41 => {}
548548
0x50 => self.exe_swap_buffers(entry.param),
549549
0x60 => self.exe_viewport(entry.param),
550-
0x70 => {
551-
// todo!()
552-
}
553-
0x71 => {
554-
// todo!()
555-
}
556-
0x72 => {
557-
// todo!()
558-
}
550+
0x70 => self.exe_box_test(unsafe { params.try_into().unwrap_unchecked() }),
551+
0x71 => self.exe_pos_test(unsafe { params.try_into().unwrap_unchecked() }),
552+
0x72 => self.exe_vec_test(entry.param),
559553
_ => {
560554
todo!("{:x}", entry.cmd);
561555
}
@@ -1013,6 +1007,101 @@ impl Gpu3DRegisters {
10131007
self.viewport_next[3] = (191 - viewport.y1() as u16) - self.viewport_next[1] + 1;
10141008
}
10151009

1010+
fn exe_box_test(&mut self, params: [u32; 3]) {
1011+
let mut box_test_coords = [
1012+
params[0] as i16,
1013+
(params[0] >> 16) as i16,
1014+
params[1] as i16,
1015+
(params[1] >> 16) as i16,
1016+
params[2] as i16,
1017+
(params[2] >> 16) as i16,
1018+
];
1019+
1020+
box_test_coords[3] += box_test_coords[0];
1021+
box_test_coords[4] += box_test_coords[1];
1022+
box_test_coords[5] += box_test_coords[2];
1023+
1024+
const INDICES: [u8; 8 * 3] = [0, 1, 2, 3, 1, 2, 0, 4, 2, 0, 1, 5, 3, 4, 2, 3, 1, 5, 0, 4, 5, 3, 4, 5];
1025+
1026+
if self.clip_dirty {
1027+
self.matrices.clip = self.matrices.model * self.matrices.proj;
1028+
self.clip_dirty = false;
1029+
}
1030+
1031+
let mut vertices = [Vectori32::<4>::default(); 8];
1032+
for i in 0..8 {
1033+
vertices[i][0] = box_test_coords[INDICES[i * 3 + 0] as usize] as i32;
1034+
vertices[i][1] = box_test_coords[INDICES[i * 3 + 1] as usize] as i32;
1035+
vertices[i][2] = box_test_coords[INDICES[i * 3 + 2] as usize] as i32;
1036+
vertices[i][3] = 1 << 12;
1037+
vertices[i] *= self.matrices.clip;
1038+
}
1039+
1040+
let faces = [
1041+
[vertices[0], vertices[1], vertices[4], vertices[2]],
1042+
[vertices[3], vertices[5], vertices[7], vertices[6]],
1043+
[vertices[3], vertices[5], vertices[1], vertices[0]],
1044+
[vertices[6], vertices[7], vertices[4], vertices[2]],
1045+
[vertices[0], vertices[3], vertices[6], vertices[2]],
1046+
[vertices[1], vertices[5], vertices[7], vertices[4]],
1047+
];
1048+
1049+
self.test_queue -= params.len() as u32;
1050+
if self.test_queue == 0 {
1051+
self.gx_stat.set_box_pos_vec_test_busy(false);
1052+
}
1053+
1054+
for i in 0..6 {
1055+
let mut size = 4;
1056+
let mut clipped = [Vectori32::<4>::default(); 10];
1057+
1058+
clip_polygon(&faces[i], &mut clipped, &mut size);
1059+
1060+
if size > 0 {
1061+
self.gx_stat.set_box_test_result(true);
1062+
return;
1063+
}
1064+
}
1065+
1066+
self.gx_stat.set_box_test_result(false);
1067+
}
1068+
1069+
fn exe_pos_test(&mut self, params: [u32; 2]) {
1070+
self.saved_vertex.coords[0] = params[0] as i16 as i32;
1071+
self.saved_vertex.coords[1] = (params[0] >> 16) as i16 as i32;
1072+
self.saved_vertex.coords[2] = (params[1]) as i16 as i32;
1073+
self.saved_vertex.coords[3] = 1 << 12;
1074+
1075+
if self.clip_dirty {
1076+
self.matrices.clip = self.matrices.model * self.matrices.proj;
1077+
self.clip_dirty = false;
1078+
}
1079+
1080+
self.pos_result = self.saved_vertex.coords * self.matrices.clip;
1081+
1082+
self.test_queue -= params.len() as u32;
1083+
if self.test_queue == 0 {
1084+
self.gx_stat.set_box_pos_vec_test_busy(false);
1085+
}
1086+
}
1087+
1088+
fn exe_vec_test(&mut self, param: u32) {
1089+
let mut vector = Vectori32::<3>::default();
1090+
vector[0] = (((param & 0x000003FF) << 6) as i16 as i32) >> 3;
1091+
vector[1] = (((param & 0x000FFC00) >> 4) as i16 as i32) >> 3;
1092+
vector[2] = (((param & 0x3FF00000) >> 14) as i16 as i32) >> 3;
1093+
1094+
vector *= self.matrices.vec;
1095+
self.vec_result[0] = ((vector[0] << 3) as i16) >> 3;
1096+
self.vec_result[1] = ((vector[1] << 3) as i16) >> 3;
1097+
self.vec_result[2] = ((vector[2] << 3) as i16) >> 3;
1098+
1099+
self.test_queue -= 1;
1100+
if self.test_queue == 0 {
1101+
self.gx_stat.set_box_pos_vec_test_busy(false);
1102+
}
1103+
}
1104+
10161105
fn process_vertices(&mut self) {
10171106
let [x, y, w, h] = *self.viewport.as_ref();
10181107
let Self { vertices, .. } = self;
@@ -1095,20 +1184,22 @@ impl Gpu3DRegisters {
10951184
self.saved_polygon.size = size;
10961185
self.saved_polygon.vertices_index = self.vertices.count_in - size;
10971186

1098-
let mut unclipped = [Vertex::default(); 4];
1099-
unclipped[..size].copy_from_slice(&self.vertices.ins[self.saved_polygon.vertices_index..self.saved_polygon.vertices_index + size]);
1187+
let mut unclipped = [Vectori32::<4>::default(); 4];
1188+
for i in 0..size {
1189+
unclipped[i] = self.vertices.ins[self.saved_polygon.vertices_index + i].coords;
1190+
}
11001191

11011192
if self.polygon_type == PolygonType::QuadliteralStrips {
11021193
unclipped.swap(2, 3);
11031194
self.vertices.ins.swap(self.saved_polygon.vertices_index + 2, self.saved_polygon.vertices_index + 3);
11041195
}
11051196

1106-
let x1 = (unclipped[1].coords[0] - unclipped[0].coords[0]) as i64;
1107-
let y1 = (unclipped[1].coords[1] - unclipped[0].coords[1]) as i64;
1108-
let w1 = (unclipped[1].coords[3] - unclipped[0].coords[3]) as i64;
1109-
let x2 = (unclipped[2].coords[0] - unclipped[0].coords[0]) as i64;
1110-
let y2 = (unclipped[2].coords[1] - unclipped[0].coords[1]) as i64;
1111-
let w2 = (unclipped[2].coords[3] - unclipped[0].coords[3]) as i64;
1197+
let x1 = (unclipped[1][0] - unclipped[0][0]) as i64;
1198+
let y1 = (unclipped[1][1] - unclipped[0][1]) as i64;
1199+
let w1 = (unclipped[1][3] - unclipped[0][3]) as i64;
1200+
let x2 = (unclipped[2][0] - unclipped[0][0]) as i64;
1201+
let y2 = (unclipped[2][1] - unclipped[0][1]) as i64;
1202+
let w2 = (unclipped[2][3] - unclipped[0][3]) as i64;
11121203

11131204
let mut xc = y1 * w2 - w1 * y2;
11141205
let mut yc = w1 * x2 - x1 * w2;
@@ -1120,7 +1211,7 @@ impl Gpu3DRegisters {
11201211
wc >>= 4;
11211212
}
11221213

1123-
let mut dot = xc * unclipped[0].coords[0] as i64 + yc * unclipped[0].coords[1] as i64 + wc * unclipped[0].coords[3] as i64;
1214+
let mut dot = xc * unclipped[0][0] as i64 + yc * unclipped[0][1] as i64 + wc * unclipped[0][3] as i64;
11241215

11251216
self.saved_polygon.clockwise = dot < 0;
11261217

@@ -1131,7 +1222,7 @@ impl Gpu3DRegisters {
11311222
self.clockwise = !self.clockwise;
11321223
}
11331224

1134-
let mut clipped = [Vertex::default(); 10];
1225+
let mut clipped = [Vectori32::<4>::default(); 10];
11351226
let cull = (!self.render_front && dot > 0) || (!self.render_back && dot < 0);
11361227
let mut clipped_size = self.saved_polygon.size;
11371228
let clip = if cull { false } else { clip_polygon(&unclipped, &mut clipped, &mut clipped_size) };
@@ -1257,6 +1348,7 @@ impl Gpu3DRegisters {
12571348
}
12581349
0x70 | 0x71 | 0x72 => {
12591350
self.test_queue += 1;
1351+
self.gx_stat.set_box_pos_vec_test_busy(true);
12601352
}
12611353
_ => {}
12621354
}
@@ -1278,6 +1370,18 @@ impl Gpu3DRegisters {
12781370
u32::from(self.gx_stat)
12791371
}
12801372

1373+
pub fn get_ram_count(&self) -> u32 {
1374+
((self.vertices.count_in as u32) << 16) | (self.polygons.count_in as u32)
1375+
}
1376+
1377+
pub fn get_pos_result(&self, index: usize) -> u32 {
1378+
self.pos_result[index] as u32
1379+
}
1380+
1381+
pub fn get_vec_result(&self, index: usize) -> u16 {
1382+
self.vec_result[index] as u16
1383+
}
1384+
12811385
pub fn set_gx_fifo(&mut self, mask: u32, value: u32, emu: &mut Emu) {
12821386
if self.gx_fifo == 0 {
12831387
self.gx_fifo = value & mask;

src/core/memory/io_arm9.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -108,14 +108,14 @@ impl IoArm9 {
108108
io8(0x300) => get_cpu_regs!(emu, ARM9).post_flg,
109109
io16(0x304) => common.gpu.pow_cnt1,
110110
io32(0x600) => common.gpu.gpu_3d_regs.get_gx_stat(),
111-
io32(0x604) => todo!(),
112-
io32(0x620) => todo!(),
113-
io32(0x624) => todo!(),
114-
io32(0x628) => todo!(),
115-
io32(0x62C) => todo!(),
116-
io16(0x630) => todo!(),
117-
io16(0x632) => todo!(),
118-
io16(0x634) => todo!(),
111+
io32(0x604) => common.gpu.gpu_3d_regs.get_ram_count(),
112+
io32(0x620) => common.gpu.gpu_3d_regs.get_pos_result(0),
113+
io32(0x624) => common.gpu.gpu_3d_regs.get_pos_result(1),
114+
io32(0x628) => common.gpu.gpu_3d_regs.get_pos_result(2),
115+
io32(0x62C) => common.gpu.gpu_3d_regs.get_pos_result(3),
116+
io16(0x630) => common.gpu.gpu_3d_regs.get_vec_result(0),
117+
io16(0x632) => common.gpu.gpu_3d_regs.get_vec_result(1),
118+
io16(0x634) => common.gpu.gpu_3d_regs.get_vec_result(2),
119119
io32(0x640) => common.gpu.gpu_3d_regs.get_clip_mtx_result(0),
120120
io32(0x644) => common.gpu.gpu_3d_regs.get_clip_mtx_result(1),
121121
io32(0x648) => common.gpu.gpu_3d_regs.get_clip_mtx_result(2),

0 commit comments

Comments
 (0)