diff --git a/bff-cli/src/lz.rs b/bff-cli/src/lz.rs index 6444339..61e156c 100644 --- a/bff-cli/src/lz.rs +++ b/bff-cli/src/lz.rs @@ -4,6 +4,8 @@ use std::io::{self, BufWriter, Cursor, Read, Write}; use bff::lz::{ arcode_compress_data_with_header_writer, arcode_decompress_data_with_header_parser, + gzip_compress_data_with_header_writer, + gzip_decompress_data_with_header_parser, lz4_compress_data_with_header_writer, lz4_decompress_data_with_header_parser, lzo_compress, @@ -32,6 +34,7 @@ pub enum LzAlgorithm { Lz4, Arcode, Zlib, + Gzip, } fn lz_internal( @@ -51,6 +54,7 @@ fn lz_internal( LzAlgorithm::Lz4 => lz4_compress_data_with_header_writer(&buf, &mut writer, endian)?, LzAlgorithm::Arcode => arcode_compress_data_with_header_writer(&buf, &mut writer, endian)?, LzAlgorithm::Zlib => zlib_compress_data_with_header_writer(&buf, &mut writer, endian)?, + LzAlgorithm::Gzip => gzip_compress_data_with_header_writer(&buf, &mut writer, endian)?, }; compressed.write_all(&writer.into_inner())?; @@ -114,6 +118,7 @@ fn unlz_internal( LzAlgorithm::Lz4 => lz4_decompress_data_with_header_parser(&mut reader, endian)?, LzAlgorithm::Arcode => arcode_decompress_data_with_header_parser(&mut reader, endian)?, LzAlgorithm::Zlib => zlib_decompress_data_with_header_parser(&mut reader, endian)?, + LzAlgorithm::Gzip => gzip_decompress_data_with_header_parser(&mut reader, endian)?, }; uncompressed.write_all(&decompressed)?; diff --git a/bff-cli/src/main.rs b/bff-cli/src/main.rs index 6ee20ba..e283c5b 100644 --- a/bff-cli/src/main.rs +++ b/bff-cli/src/main.rs @@ -209,8 +209,16 @@ fn main() -> BffCliResult<()> { ), Commands::RoundTrip { bigfile } => round_trip::round_trip(bigfile), Commands::Csc { input, output, key } => csc::csc(input, output, key), - Commands::ExtractPsc { psc, directory, algorithm } => psc::extract_psc(psc, directory, algorithm), - Commands::CreatePsc { directory, psc, algorithm } => psc::create_psc(directory, psc, algorithm), + Commands::ExtractPsc { + psc, + directory, + algorithm, + } => psc::extract_psc(psc, directory, algorithm), + Commands::CreatePsc { + directory, + psc, + algorithm, + } => psc::create_psc(directory, psc, algorithm), Commands::ExtractFatLin { fat, lin, diff --git a/bff-cli/src/psc.rs b/bff-cli/src/psc.rs index c33d57e..2bfa920 100644 --- a/bff-cli/src/psc.rs +++ b/bff-cli/src/psc.rs @@ -12,6 +12,7 @@ use crate::error::BffCliResult; pub enum PscAlgorithm { None, Lz4, + Gzip, } impl From for bff::tsc::PscAlgorithm { @@ -19,15 +20,12 @@ impl From for bff::tsc::PscAlgorithm { match algorithm { PscAlgorithm::None => Self::None, PscAlgorithm::Lz4 => Self::Lz4, + PscAlgorithm::Gzip => Self::Gzip, } } } -pub fn extract_psc( - psc: &Path, - directory: &Path, - algorithm: &PscAlgorithm, -) -> BffCliResult<()> { +pub fn extract_psc(psc: &Path, directory: &Path, algorithm: &PscAlgorithm) -> BffCliResult<()> { let mut psc_reader = BufReader::new(File::open(psc)?); let psc = Psc::read(&mut psc_reader, (*algorithm).into())?; @@ -63,11 +61,7 @@ fn read_files_into_psc_recursively( Ok(()) } -pub fn create_psc( - directory: &Path, - psc_path: &Path, - algorithm: &PscAlgorithm, -) -> BffCliResult<()> { +pub fn create_psc(directory: &Path, psc_path: &Path, algorithm: &PscAlgorithm) -> BffCliResult<()> { let mut psc = Psc::default(); read_files_into_psc_recursively(&mut psc, directory, directory)?; diff --git a/bff/src/lz/gzip.rs b/bff/src/lz/gzip.rs new file mode 100644 index 0000000..e8281a5 --- /dev/null +++ b/bff/src/lz/gzip.rs @@ -0,0 +1,47 @@ +use std::io::{Read, Seek, Write}; + +use binrw::{BinResult, Endian}; +use flate2::read::MultiGzDecoder; +use flate2::write::GzEncoder; +use flate2::Compression; + +use crate::BffResult; + +#[binrw::writer(writer)] +pub fn gzip_compress_data_with_header_writer_internal(data: &[u8]) -> BinResult<()> { + let mut gz = GzEncoder::new(writer, Compression::fast()); + gz.write_all(data)?; + Ok(()) +} + +pub fn gzip_compress_data_with_header_writer( + data: &[u8], + writer: &mut W, + endian: Endian, +) -> BffResult<()> { + Ok(gzip_compress_data_with_header_writer_internal( + data, + writer, + endian, + (), + )?) +} + +#[binrw::parser(reader)] +pub fn gzip_decompress_data_with_header_parser_internal() -> BinResult> { + let mut gz = MultiGzDecoder::new(reader); + let mut buf = Vec::new(); + gz.read_to_end(&mut buf)?; + Ok(buf) +} + +pub fn gzip_decompress_data_with_header_parser( + reader: &mut R, + endian: Endian, +) -> BffResult> { + Ok(gzip_decompress_data_with_header_parser_internal( + reader, + endian, + (), + )?) +} diff --git a/bff/src/lz/mod.rs b/bff/src/lz/mod.rs index 95fb008..6d8a925 100644 --- a/bff/src/lz/mod.rs +++ b/bff/src/lz/mod.rs @@ -1,10 +1,12 @@ mod arcode; +mod gzip; mod lz4; mod lzo; mod lzrs; mod zlib; pub use arcode::*; +pub use gzip::*; pub use lz4::*; pub use lzo::*; pub use lzrs::*; diff --git a/bff/src/tsc/psc.rs b/bff/src/tsc/psc.rs index 48ed09c..84d409d 100644 --- a/bff/src/tsc/psc.rs +++ b/bff/src/tsc/psc.rs @@ -8,6 +8,8 @@ use itertools::Itertools; use crate::helpers::StringUntilNull; use crate::lz::{ + gzip_compress_data_with_header_writer_internal, + gzip_decompress_data_with_header_parser_internal, lz4_compress_data_with_header_writer_internal, lz4_decompress_data_with_header_parser_internal, }; @@ -43,10 +45,6 @@ impl BinRead for Psc { while reader.stream_position()? != end { let path_string = StringUntilNull::read(reader)?.0; let path = PathBuf::from(path_string); - let cr = u8::read_le(reader)?; - assert_eq!(cr, 0x0D); - let lf = u8::read_le(reader)?; - assert_eq!(lf, 0x0A); let data = StringUntilNull::read(reader)?.0; psc.tscs.insert(path, data); } @@ -73,7 +71,7 @@ impl BinWrite for Psc { .join("\\") .as_bytes(), )?; - writer.write_all(&[0x00, 0x0D, 0x0A])?; + writer.write_all(&[0x00])?; writer.write_all(data.as_bytes())?; writer.write_all(&[0x00])?; } @@ -86,13 +84,11 @@ impl BinWrite for Psc { pub enum PscAlgorithm { None, Lz4, + Gzip, } impl Psc { - pub fn read( - reader: &mut R, - psc_compression: PscAlgorithm, - ) -> BffResult { + pub fn read(reader: &mut R, psc_compression: PscAlgorithm) -> BffResult { match psc_compression { PscAlgorithm::None => Ok(::read(reader)?), PscAlgorithm::Lz4 => { @@ -102,6 +98,15 @@ impl Psc { (), )?); + Ok(::read(&mut psc_data)?) + } + PscAlgorithm::Gzip => { + let mut psc_data = Cursor::new(gzip_decompress_data_with_header_parser_internal( + reader, + Endian::Little, + (), + )?); + Ok(::read(&mut psc_data)?) } } @@ -127,6 +132,14 @@ impl Psc { (), )?; } + PscAlgorithm::Gzip => { + gzip_compress_data_with_header_writer_internal( + &psc_data.into_inner(), + writer, + Endian::Little, + (), + )?; + } } Ok(())