From 012743e245fff448dcd163af5152ed5bacde90c9 Mon Sep 17 00:00:00 2001 From: Kevin Marsolais Date: Mon, 20 May 2024 10:45:27 -0700 Subject: [PATCH] Replace `libsquish-wrapper` with `texpresso`, equivalent Rust crate (#38) Replace `libsquish-wrapper`, a wrapper around a C++ dependency, with `texpresso`, a Rust crate providing the same compression and decompression algorithm, but without support for Gamecube format. Conversion to Gamecube format was added manually. --- .gitmodules | 3 --- Cargo.lock | 20 +++++++++----- Cargo.toml | 3 +-- libsquish_wrapper/Cargo.toml | 8 ------ libsquish_wrapper/build.rs | 17 ------------ libsquish_wrapper/libSquish | 1 - libsquish_wrapper/src/lib.rs | 32 ----------------------- libsquish_wrapper/src/wrapper.cpp | 26 ------------------- src/bin/txtr_converter.rs | 11 +++----- src/txtr_conversions.rs | 43 ++++++++++++++++++++++++++++--- 10 files changed, 57 insertions(+), 107 deletions(-) delete mode 100644 .gitmodules delete mode 100644 libsquish_wrapper/Cargo.toml delete mode 100644 libsquish_wrapper/build.rs delete mode 160000 libsquish_wrapper/libSquish delete mode 100644 libsquish_wrapper/src/lib.rs delete mode 100644 libsquish_wrapper/src/wrapper.cpp diff --git a/.gitmodules b/.gitmodules deleted file mode 100644 index 75645a5b..00000000 --- a/.gitmodules +++ /dev/null @@ -1,3 +0,0 @@ -[submodule "libsquish_wrapper/libSquish"] - path = libsquish_wrapper/libSquish - url = https://github.com/AxioDL/libSquish diff --git a/Cargo.lock b/Cargo.lock index c6f1da00..c48eb3be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -569,11 +569,10 @@ dependencies = [ ] [[package]] -name = "libsquish_wrapper" -version = "0.1.0" -dependencies = [ - "cc", -] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" [[package]] name = "log" @@ -929,7 +928,6 @@ dependencies = [ "json_data", "json_strip", "lazy_static", - "libsquish_wrapper", "memmap", "nalgebra", "nod", @@ -945,6 +943,7 @@ dependencies = [ "serde_json", "ssmarshal", "structs", + "texpresso", "winapi", ] @@ -1182,6 +1181,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "texpresso" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8277e703c934b9693d0773d5749faacc6366b3d81d012da556a4cfd4ab87f336" +dependencies = [ + "libm", +] + [[package]] name = "textwrap" version = "0.11.0" diff --git a/Cargo.toml b/Cargo.toml index 7f4f279f..2f465e53 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,12 +29,12 @@ dol_linker = { path = "dol_linker" } dol_symbol_table = { path = "generated/dol_symbol_table" } json_data = { path = "generated/json_data" } json_strip = { path = "generated/json_strip" } -libsquish_wrapper = { path = "libsquish_wrapper" } ppcasm = { path = "ppcasm" } reader_writer.workspace = true rel_files = { path = "generated/rel_files" } resource_info_table.workspace = true structs = { path = "structs" } +texpresso = "2.0.1" [profile.release] lto = "thin" @@ -51,7 +51,6 @@ members = [ "generated/dol_symbol_table/dol_symbol_table_macro", "generated/json_data", "generated/json_strip", - "libsquish_wrapper", "ppcasm", "ppcasm/ppcasm_macro", "reader_writer", diff --git a/libsquish_wrapper/Cargo.toml b/libsquish_wrapper/Cargo.toml deleted file mode 100644 index 6db8f28b..00000000 --- a/libsquish_wrapper/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "libsquish_wrapper" -version = "0.1.0" -authors = ["April Wade "] -edition = "2021" - -[build-dependencies] -cc.workspace = true diff --git a/libsquish_wrapper/build.rs b/libsquish_wrapper/build.rs deleted file mode 100644 index 47b03e13..00000000 --- a/libsquish_wrapper/build.rs +++ /dev/null @@ -1,17 +0,0 @@ -fn main() { - cc::Build::new() - .include("libSquish") - .file("src/wrapper.cpp") - .file("libSquish/alpha.cpp") - .file("libSquish/clusterfit.cpp") - .file("libSquish/colourblock.cpp") - .file("libSquish/colourblockGCN.cpp") - .file("libSquish/colourfit.cpp") - .file("libSquish/colourset.cpp") - .file("libSquish/maths.cpp") - .file("libSquish/rangefit.cpp") - .file("libSquish/singlecolourfit.cpp") - .file("libSquish/squish.cpp") - .cpp(true) - .compile("libSquish"); -} diff --git a/libsquish_wrapper/libSquish b/libsquish_wrapper/libSquish deleted file mode 160000 index fd5e6f4f..00000000 --- a/libsquish_wrapper/libSquish +++ /dev/null @@ -1 +0,0 @@ -Subproject commit fd5e6f4fe294bcdde24e591fcef37dd5d740e060 diff --git a/libsquish_wrapper/src/lib.rs b/libsquish_wrapper/src/lib.rs deleted file mode 100644 index fab06f55..00000000 --- a/libsquish_wrapper/src/lib.rs +++ /dev/null @@ -1,32 +0,0 @@ -extern "C" { - - // fn libsquish_CompressMasked(rgba: *const u8, mask: i32, block: *const u8, flags: i32, metric: *mut f32); - fn libsquish_Compress(rgba: *const u8, block: *mut u8, flags: i32, metric: *mut f32); - fn libsquish_Decompress(rgba: *mut u8, block: *const u8, flags: i32); - // fn libsquish_GetStorageRequirements(width: i32, height: i32, flags: i32) -> i32; - // fn libsquish_CompressImage(rgba: *const u8, width: i32, height: i32, blocks: *mut u8, flags: i32, metric: *mut f32); - - // fn libsquish_DecompressImage(rgba: *mut u8, width: i32, height: i32, blocks: *const u8, flags: i32); -} - -pub fn compress_dxt1gcn_block(rgba: &[[u8; 4]; 16], block: &mut [u8; 8]) { - unsafe { - libsquish_Compress( - rgba.as_ptr().cast(), - block.as_mut_ptr(), - ( 1 << 9 )/* kDxt1GCN */ | ( 1 << 8 ), /* kColourIterativeClusterFit */ - std::ptr::null_mut(), - ) - } -} - -pub fn decompress_dxt1gcn_block(rgba: &mut [[u8; 4]; 16], block: &[u8; 8]) { - assert!(block.len() >= 8); - unsafe { - libsquish_Decompress( - rgba.as_mut_ptr().cast(), - block.as_ptr(), - 1 << 9, /* kDxt1GCN */ - ) - } -} diff --git a/libsquish_wrapper/src/wrapper.cpp b/libsquish_wrapper/src/wrapper.cpp deleted file mode 100644 index c48ecddd..00000000 --- a/libsquish_wrapper/src/wrapper.cpp +++ /dev/null @@ -1,26 +0,0 @@ -#include "squish.h" - -extern "C" { - -// void libsquish_CompressMasked(u8 const* rgba, int mask, void* block, int flags, float* metric) { -// squish::CompressMasked(rgba, mask, block, flags, metric); -// } -void libsquish_Compress(const squish::u8* rgba, void* block, int flags, float* metric) { - squish::Compress(rgba, block, flags, metric); -} -void libsquish_Decompress(squish::u8* rgba, const void* block, int flags) { - squish::Decompress(rgba, block, flags); -} -// int libsquish_GetStorageRequirements(int width, int height, int flags) { -// squish::GetStorageRequirements(width, height, flags); -// } - -// void libsquish_CompressImage(u8 const* rgba, int width, int height, void* blocks, int flags, float* metric) { -// squish::CompressImage(rgba, width, height, blocks, flags, metric); -// } - -// void libsquish_DecompressImage(u8* rgba, int width, int height, void const* blocks, int flags) { -// squish::DecompressImage(rgba, width, height, blocks, flags); -// } - -} diff --git a/src/bin/txtr_converter.rs b/src/bin/txtr_converter.rs index 26d39256..c47ac925 100644 --- a/src/bin/txtr_converter.rs +++ b/src/bin/txtr_converter.rs @@ -5,7 +5,7 @@ use image::{ codecs::png::{PngDecoder, PngEncoder}, ColorType, ImageDecoder, }; -use libsquish_wrapper::{compress_dxt1gcn_block, decompress_dxt1gcn_block}; +use randomprime::txtr_conversions::{compress_dxt1gcn_block, decompress_dxt1gcn_block}; use reader_writer::{Readable, Reader, Writable}; use structs::{Txtr, TxtrFormat, TxtrPaletteFormat}; @@ -445,13 +445,8 @@ impl TxtrFormatExt for TxtrFormat { } TxtrFormat::Rgba8 => pixels.copy_from_slice(block), TxtrFormat::Cmpr => { - let mut decoded_dxt1_block = [[0u8; 4]; 16]; for i in 0..4 { - decompress_dxt1gcn_block( - &mut decoded_dxt1_block, - block[i * 8..(i + 1) * 8].try_into().unwrap(), - ); - + let decoded_dxt1_block = decompress_dxt1gcn_block(&block[i * 8..(i + 1) * 8]); let outer_x = i % 2 * 4; let outer_y = i / 2 * 4; for (k, decoded_pixel) in decoded_dxt1_block.iter().enumerate() { @@ -542,7 +537,7 @@ impl TxtrFormatExt for TxtrFormat { sub_block_pixel[..].copy_from_slice(&pixels[start..start + 4]); } - compress_dxt1gcn_block(&sub_block_pixels, sub_block.try_into().unwrap()); + compress_dxt1gcn_block(sub_block_pixels, sub_block); } } } diff --git a/src/txtr_conversions.rs b/src/txtr_conversions.rs index afa37ce6..ce1235a2 100644 --- a/src/txtr_conversions.rs +++ b/src/txtr_conversions.rs @@ -1,7 +1,7 @@ use std::convert::TryInto; -use libsquish_wrapper::{compress_dxt1gcn_block, decompress_dxt1gcn_block}; use resource_info_table::{resource_info, ResourceInfo}; +use texpresso::Format; // 0 - Power // 1 - Gravity @@ -186,8 +186,7 @@ impl Iterator for CmprPixelIter { pub fn cmpr_decompress(compressed: &[u8], width: usize, height: usize, decompressed: &mut [u8]) { let cmpr_iter = CmprPixelIter::new(width, height); for (chunk, (first_pixel_x, first_pixel_y)) in compressed.chunks_exact(8).zip(cmpr_iter) { - let mut decompressed_pixels = [[0u8; 4]; 16]; - decompress_dxt1gcn_block(&mut decompressed_pixels, chunk.try_into().unwrap()); + let decompressed_pixels = decompress_dxt1gcn_block(chunk); for y in 0..4 { for x in 0..4 { let pixel_x = first_pixel_x + x; @@ -216,7 +215,7 @@ pub fn cmpr_compress(uncompressed: &[u8], width: usize, height: usize, compresse } } - compress_dxt1gcn_block(&uncompressed_pixels, chunk.try_into().unwrap()); + compress_dxt1gcn_block(uncompressed_pixels, chunk); } } @@ -266,3 +265,39 @@ pub fn huerotate_in_place(image: &mut [u8], width: usize, height: usize, matrix: } } } + +pub fn compress_dxt1gcn_block(rgba: [[u8; 4]; 16], block: &mut [u8]) { + Format::Bc1.compress_block_masked( + rgba, + 0xFFFF, + texpresso::Params { + algorithm: texpresso::Algorithm::IterativeClusterFit, + ..Default::default() + }, + block, + ); + block.swap(0, 1); + block.swap(2, 3); + for byte in block[4..8].iter_mut() { + *byte = reverse_byte(*byte); + } +} + +pub fn decompress_dxt1gcn_block(block: &[u8]) -> [[u8; 4]; 16] { + let mut compressed = [0u8; 8]; + compressed[0] = block[1]; + compressed[1] = block[0]; + compressed[2] = block[3]; + compressed[3] = block[2]; + for (byte, val) in compressed[4..8].iter_mut().zip(block[4..8].iter()) { + *byte = reverse_byte(*val); + } + Format::Bc1.decompress_block(&compressed) +} + +fn reverse_byte(byte: u8) -> u8 { + (byte & 0b00000011) << 6 + | (byte & 0b00001100) << 2 + | (byte & 0b00110000) >> 2 + | (byte & 0b11000000) >> 6 +}