11// Adapted from https://github.com/bartlomiejduda/ReverseBox/blob/main/reversebox/image/swizzling/swizzle_x360.py
22
3+ use anyhow:: Context ;
34use log:: warn;
45
56use crate :: texture:: dxgi:: XenosSurfaceFormat ;
@@ -70,20 +71,29 @@ fn untile_x360_image_data(
7071
7172 let width_in_blocks = image_width / block_pixel_size;
7273 let height_in_blocks = image_height / block_pixel_size;
73- let slice_size = width_in_blocks * height_in_blocks * texel_byte_pitch;
74+
75+ let padded_width_in_blocks = ( width_in_blocks + 31 ) & !31 ;
76+ let padded_height_in_blocks = ( height_in_blocks + 31 ) & !31 ;
77+
78+ let slice_size = padded_width_in_blocks * padded_height_in_blocks * texel_byte_pitch;
7479
7580 for slice in 0 ..image_depth {
76- let slice_src = & image_data[ slice * slice_size..] ;
77- let slice_dest = & mut converted_data[ slice * slice_size..] ;
78-
79- for j in 0 ..height_in_blocks {
80- for i in 0 ..width_in_blocks {
81- let block_offset = j * width_in_blocks + i;
82- let x = xg_address_2d_tiled_x ( block_offset, width_in_blocks, texel_byte_pitch) ;
83- let y = xg_address_2d_tiled_y ( block_offset, width_in_blocks, texel_byte_pitch) ;
84- let src_byte_offset = j * width_in_blocks * texel_byte_pitch + i * texel_byte_pitch;
85- let dest_byte_offset =
86- y * width_in_blocks * texel_byte_pitch + x * texel_byte_pitch;
81+ let slice_src = image_data
82+ . get ( slice * slice_size..)
83+ . context ( "Texture slice source out of bounds" ) ?;
84+ let slice_dest = converted_data
85+ . get_mut ( slice * slice_size..)
86+ . context ( "Texture slice dest out of bounds" ) ?;
87+
88+ for j in 0 ..padded_height_in_blocks {
89+ for i in 0 ..padded_width_in_blocks {
90+ let block_offset = j * padded_width_in_blocks + i;
91+ let x =
92+ xg_address_2d_tiled_x ( block_offset, padded_width_in_blocks, texel_byte_pitch) ;
93+ let y =
94+ xg_address_2d_tiled_y ( block_offset, padded_width_in_blocks, texel_byte_pitch) ;
95+ let src_byte_offset = block_offset * texel_byte_pitch;
96+ let dest_byte_offset = ( y * width_in_blocks + x) * texel_byte_pitch;
8797
8898 if dest_byte_offset + texel_byte_pitch > slice_dest. len ( )
8999 || src_byte_offset + texel_byte_pitch > slice_src. len ( )
@@ -94,6 +104,9 @@ fn untile_x360_image_data(
94104 if deswizzle {
95105 match slice_src. get ( src_byte_offset..src_byte_offset + texel_byte_pitch) {
96106 Some ( source) => {
107+ if source. iter ( ) . all ( |& b| b == 0 ) {
108+ continue ;
109+ }
97110 slice_dest[ dest_byte_offset..dest_byte_offset + texel_byte_pitch]
98111 . copy_from_slice ( source) ;
99112 }
@@ -168,11 +181,18 @@ impl Deswizzler for XenosDetiler {
168181 } ;
169182
170183 let mut source = data. to_vec ( ) ;
171- if ! matches ! (
184+ if matches ! (
172185 format,
173- XenosSurfaceFormat :: k_8_8_8_8
174- | XenosSurfaceFormat :: k_8_8_8_8_A
175- | XenosSurfaceFormat :: k_8_8_8_8_AS_16_16_16_16
186+ XenosSurfaceFormat :: k_DXT1
187+ | XenosSurfaceFormat :: k_DXT1_AS_16_16_16_16
188+ | XenosSurfaceFormat :: k_DXN
189+ | XenosSurfaceFormat :: k_DXT2_3
190+ | XenosSurfaceFormat :: k_DXT2_3_AS_16_16_16_16
191+ | XenosSurfaceFormat :: k_DXT3A
192+ | XenosSurfaceFormat :: k_DXT3A_AS_1_1_1_1
193+ | XenosSurfaceFormat :: k_DXT4_5
194+ | XenosSurfaceFormat :: k_DXT4_5_AS_16_16_16_16
195+ | XenosSurfaceFormat :: k_DXT5A
176196 ) {
177197 swap_byte_order_x360 ( & mut source) ;
178198 }
0 commit comments