Skip to content

Commit 43f971f

Browse files
committed
texture: Improve x360 detiling
1 parent dad30a9 commit 43f971f

File tree

1 file changed

+36
-16
lines changed

1 file changed

+36
-16
lines changed

src/texture/swizzle/swizzle_xbox.rs

Lines changed: 36 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
// Adapted from https://github.com/bartlomiejduda/ReverseBox/blob/main/reversebox/image/swizzling/swizzle_x360.py
22

3+
use anyhow::Context;
34
use log::warn;
45

56
use 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

Comments
 (0)