diff --git a/Cargo.toml b/Cargo.toml index 944d6aa..faa67d7 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ game_install = [] # enables support for extracting visual data, such as models, textures, materials, etc. # this enables a bunch of dependencies! # tip: can be safely turned off for launchers and other tools that simply need to extract the bare minimum of data -visual_data = ["dep:half", "dep:bitflags", "dep:texpresso"] +visual_data = ["dep:half", "dep:bitflags", "dep:texture2ddecoder"] # testing only features retail_game_testing = [] @@ -70,4 +70,4 @@ half = { version = "2", optional = true } bitflags = { version = "1.3", optional = true } # needed for dxt/bc decompression -texpresso = { version = "2", optional = true } \ No newline at end of file +texture2ddecoder = { version = "0.0.5", optional = true } \ No newline at end of file diff --git a/src/tex.rs b/src/tex.rs index 12af0ba..66f0fca 100644 --- a/src/tex.rs +++ b/src/tex.rs @@ -8,7 +8,7 @@ use std::io::{Cursor, Read, Seek, SeekFrom}; use binrw::BinRead; use binrw::binrw; use bitflags::bitflags; -use texpresso::Format; +use texture2ddecoder::{decode_bc1, decode_bc3, decode_bc5}; use crate::ByteSpan; // Attributes and Format are adapted from Lumina (https://github.com/NotAdam/Lumina/blob/master/src/Lumina/Data/Files/TexFile.cs) @@ -79,6 +79,8 @@ pub struct Texture { pub rgba: Vec, } +type DecodeFunction = fn(&[u8], usize, usize, &mut [u32]) -> Result<(), &'static str>; + impl Texture { /// Reads an existing TEX file pub fn from_existing(buffer: ByteSpan) -> Option { @@ -92,7 +94,7 @@ impl Texture { let mut src = vec![0u8; buffer.len() - std::mem::size_of::()]; cursor.read_exact(src.as_mut_slice()).ok()?; - let mut dst; + let mut dst : Vec; match header.format { TextureFormat::B4G4R4A4 => { @@ -119,40 +121,16 @@ impl Texture { } } TextureFormat::B8G8R8A8 => { - dst = src; + dst = src; // TODO: not correct, of course } TextureFormat::BC1 => { - dst = vec![0u8; header.width as usize * header.height as usize * 4]; - - let format = Format::Bc1; - format.decompress( - &src, - header.width as usize, - header.height as usize, - dst.as_mut_slice(), - ); + dst = Texture::decode(&src, header.width as usize, header.height as usize, decode_bc1); } TextureFormat::BC3 => { - dst = vec![0u8; header.width as usize * header.height as usize * 4]; - - let format = Format::Bc3; - format.decompress( - &src, - header.width as usize, - header.height as usize, - dst.as_mut_slice(), - ); + dst = Texture::decode(&src, header.width as usize, header.height as usize, decode_bc3); } TextureFormat::BC5 => { - dst = vec![0u8; header.width as usize * header.height as usize * 4]; - - let format = Format::Bc5; - format.decompress( - &src, - header.width as usize, - header.height as usize, - dst.as_mut_slice(), - ); + dst = Texture::decode(&src, header.width as usize, header.height as usize, decode_bc5); } } @@ -162,6 +140,25 @@ impl Texture { rgba: dst, }) } + + fn decode(src: &[u8], width: usize, height: usize, decode_func: DecodeFunction) -> Vec { + let mut image: Vec = vec![0; (width * height) as usize]; + decode_func( + &src, + width as usize, + height as usize, + &mut image, + ) + .unwrap(); + + image + .iter() + .flat_map(|x| { + let v = x.to_le_bytes(); + [v[2], v[1], v[0], v[3]] + }) + .collect::>() + } } #[cfg(test)]