Skip to content

Commit

Permalink
Add xbox file detection to apply dxt endian fix automatically. Improv…
Browse files Browse the repository at this point in the history
…e arg descriptions. Update readme.
  • Loading branch information
rob5300 committed Mar 23, 2024
1 parent d92492a commit ced8cd0
Show file tree
Hide file tree
Showing 7 changed files with 44 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "vtfx_reader"
version = "1.3.0"
version = "1.4.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
Expand Down
33 changes: 22 additions & 11 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
[![GitHub Downloads (all assets, latest release)](https://img.shields.io/github/downloads/rob5300/vtfx_reader/latest/total?sort=date)
](https://github.com/rob5300/vtfx_reader/releases/latest)

A tool to read the header + output image resources (as png) from a [VTFX file](https://developer.valvesoftware.com/wiki/VTFX_file_format). Written in rust.
A tool to read the header + output image resources (as png) from a [VTFX file](https://developer.valvesoftware.com/wiki/VTFX_file_format). Supports LZMA compressed resources as well as big endian formatted resources. Written in rust.

- Supports 360 vtf files [\*.360.vtf].
- PS3 files are also supported [\*.vtf], use the ``--no-dxt-fix`` argument to get a desired output.
- Supports 360 vtf files [\*.360.vtf]. DXT endianness is automatically fixed.
- PS3 files [\*.vtf].

*Note: Xbox 360 vtfx's usually have multiple mip levels packed into the main resource, the largest mip level will be exported.*
> [!NOTE]
> Xbox 360 vtfx's usually have multiple mip levels packed into the main resource, the largest mip level will be exported.
## Working texture export formats (Open issue to request):
- DXT1
Expand All @@ -27,29 +28,39 @@ Untested support for:

Compressed (LZMA) and non compressed images are supported. By default alpha is not exported, but can be enabled with the ``--export-alpha`` argument.

Files detected to be for the xbox 360 (v 864.8) that are in the image formats IMAGE_FORMAT_DXT1, IMAGE_FORMAT_DXT3 or IMAGE_FORMAT_DXT5 will have their endianness converted before decoding (otherwise the output will have corrupted color). PS3 files (usually v 819.8) do not need this.

## How to use
Download the latest release and run, using the arguments listed below to specify the input files and options.

## Arguments
Usage: vtfx_reader.exe [OPTIONS] --input <INPUT>

Options:
-i, --input <INPUT>
Input .vtf file path
Input path (process single file) or folder (processes all vtf files in folder)

-o, --output <OUTPUT>
Output folder
Output folder for exported images

--export-alpha
Export alpha channel
If alpha should be included in image export

--no-dxt-fix
Do not use big to little endian fix on DXT images
--force-dxt-endian-fix
Force apply big to little endian fix on DXT image resources (otherwise automatic)

--no-resource-export
Do not export any resources

--open
Auto open exported images

-h, --help
Print help (see a summary with '-h')

-V, --version
Print version

## Compiling
To compile from source, install the rust tooling [rustup](https://rustup.rs/), then use ``cargo run`` and build the project.
To compile from source, install the rust tooling [rustup](https://rustup.rs/), then use ``cargo run`` to build and run the project.

[texpresso](https://crates.io/crates/texpresso) is used to decode dxt data, and [lzma-rs](https://crates.io/crates/lzma-rs) for lzma decompression.
12 changes: 6 additions & 6 deletions src/args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@ use clap::Parser;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = "A tool to parse vtfx files (from x360 and ps3)")]
pub struct Args {
/// Input .vtf file path
/// Input path (process single file) or folder (processes all vtf files in folder)
#[arg(short, long)]
pub input: PathBuf,

/// Output folder
/// Output folder for exported images
#[arg(short, long)]
pub output: Option<PathBuf>,

/// Export alpha channel
/// If alpha should be included in image export
#[arg(long, default_value_t = false)]
pub export_alpha: bool,

/// Do not use big to little endian fix on DXT images
/// Force apply big to little endian fix on DXT image resources (otherwise automatic)
#[arg(long, default_value_t = false)]
pub no_dxt_fix: bool,
pub force_dxt_endian_fix: bool,

/// Do not export any resources
#[arg(long, default_value_t = false)]
pub no_resource_export: bool,

/// Auto open exported images
#[arg(long, default_value_t = false)]
pub open: bool,
pub open: bool
}
3 changes: 2 additions & 1 deletion src/image_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl image_format_info
}
}

///Correct endianness of dxt bc data
///Convert endianness of dxt bc data (big to little)
pub fn correct_dxt_endianness(format: &texpresso::Format, data: &mut [u8]) -> Result<(), Box<dyn Error>>
{
//https://learn.microsoft.com/en-us/windows/win32/direct3d10/d3d10-graphics-programming-guide-resources-block-compression#bc1
Expand Down Expand Up @@ -286,6 +286,7 @@ static IMAGE_FORMAT_INFO_MAP: Lazy<HashMap<ImageFormat, image_format_info>> = La
let mut map = HashMap::new();
map.insert(ImageFormat::IMAGE_FORMAT_DXT1, image_format_info::new_with_bc(3, 1, vec![0,1,2], Option::from(texpresso::Format::Bc1)));
map.insert(ImageFormat::IMAGE_FORMAT_DXT5, image_format_info::new_with_bc(4, 1, vec![0,1,2,3], Option::from(texpresso::Format::Bc3)));
map.insert(ImageFormat::IMAGE_FORMAT_DXT1_ONEBITALPHA, image_format_info::new_with_bc(4, 1, vec![0,1,2,3], Option::from(texpresso::Format::Bc1)));
map.insert(ImageFormat::IMAGE_FORMAT_RGBA16161616, image_format_info::new(4, 2, vec![0,1,2,3]));
map.insert(ImageFormat::IMAGE_FORMAT_BGRX8888, image_format_info::new(4, 1, vec![2,1,0,3]));
map.insert(ImageFormat::IMAGE_FORMAT_LINEAR_BGRX8888, image_format_info::new(4, 1, vec![2,1,0,3]));
Expand Down
8 changes: 6 additions & 2 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use std::path::Path;
use std::path::PathBuf;
use std::process::exit;
use args::Args;
use clap::builder::FalseyValueParser;
use clap::Parser;
use image::DynamicImage;
use image::GenericImage;
Expand Down Expand Up @@ -97,6 +96,11 @@ fn read_vtfx(path: &Path) -> Result<VTFXHEADER, Box<dyn Error>> {

let vtfx = VTFXHEADER::from(&buffer)?;

println!(" Vtfx is for {}", match vtfx.is_xbox() {
true => "Xbox 360",
false => "PS3/Other"
});

let dxt_hint = vtfx.hint_dx5();
if cfg!(debug_assertions) && dxt_hint
{
Expand Down Expand Up @@ -202,7 +206,7 @@ fn resource_to_image(buffer: &[u8], resource_entry_info: &ResourceEntryInfo, vtf
}
}

if !ARGS.no_dxt_fix
if vtfx.is_xbox() || ARGS.force_dxt_endian_fix
{
println!(" Applying endianness fix to resource '{res_num}' before dxt decode...");
correct_dxt_endianness(&bc_format, &mut resource_buffer)?;
Expand Down
7 changes: 6 additions & 1 deletion src/vtfx.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ impl VTFXHEADER
vtfx.compressed_size = u32::from_be_bytes(buffer[i..i+4].try_into().unwrap());
i += 4;

if cfg!(debug_assertions){ println!("[Debug] VTFX READ END: Current read position: {}, Data left: {} bytes.\n", i, buffer.len() - i); }
if cfg!(debug_assertions){ println!("[Debug] VTFX READ END: Current read position: {}, Data left: {} bytes", i, buffer.len() - i); }

vtfx.mip_count = match vtfx.no_mips() {
true => 1,
Expand Down Expand Up @@ -219,6 +219,11 @@ impl VTFXHEADER
{
self.width as usize * self.height as usize * self.get_channels() as usize
}

pub fn is_xbox(&self) -> bool
{
self.version[0] == VTF_X360_MAJOR_VERSION && self.version[1] == VTF_X360_MINOR_VERSION
}
}

impl fmt::Display for VTFXHEADER {
Expand Down

1 comment on commit ced8cd0

@alvedit
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link exe vtfx plis

Please sign in to comment.