@@ -14,7 +14,7 @@ use std::mem;
1414#[ derive( Copy , Clone , FromBits ) ]
1515pub 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 {
392392pub 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
444444impl 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;
0 commit comments