diff --git a/Cargo.toml b/Cargo.toml index dd6acfc..cac46d7 100755 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,15 +25,14 @@ libunshield = "1.4" walkdir = "2" hmac-sha512 = "1" criterion = "0.4" +# used for testing our jamcrc implementation +crc = "3" [features] retail_game_testing = [] patch_testing = [] [dependencies] -# used for jamcrc implementation, should eventually move away from it -crc = "3" - # amazing binary parsing/writing library binrw = "0.10" diff --git a/src/crc.rs b/src/crc.rs new file mode 100644 index 0000000..d987f1b --- /dev/null +++ b/src/crc.rs @@ -0,0 +1,63 @@ +pub struct JAMCRC { + table: [u32; 256] +} + +impl JAMCRC { + pub(crate) const fn new() -> Self { + let mut table: [u32; 256] = [0u32; 256]; + + let polynomial: u32 = 0xEDB88320; + let mut i = 0; + while i < table.len() { + let mut c: u32 = i as u32; + let mut j = 0; + while j < 8 { + if (c & 1u32) == 1u32 { + c = polynomial ^ (c >> 1); + } else { + c >>= 1; + } + j += 1; + } + + table[i] = c; + i += 1; + } + + Self { + table + } + } + + pub(crate) fn checksum(&self, bytes: &[u8]) -> u32 { + let mut c : u32 = 0xFFFFFFFF; + for byte in bytes { + c = self.table[((c ^ *byte as u32) & 0xFF) as usize] ^ (c >> 8); + } + + !(c ^ 0xFFFFFFFF) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::fiin::FileInfo; + use std::fs::read; + use std::path::PathBuf; + + #[test] + fn basic_parsing() { + use crc::{Crc, CRC_32_JAMCRC}; + use std::io::{Read, Seek, SeekFrom}; + + const JAMCR: Crc = Crc::::new(&CRC_32_JAMCRC); + + let bytes : [u8; 9] = [1, 1, 2, 4, 5, 6, 12, 12, 12]; + + const crc : JAMCRC = JAMCRC::new(); + + assert_eq!(JAMCR.checksum(&bytes), + crc.checksum(&bytes)) + } +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 1de5ad2..05d4953 100755 --- a/src/lib.rs +++ b/src/lib.rs @@ -67,3 +67,5 @@ pub mod tex; /// Reading material files (MTRL) pub mod mtrl; + +mod crc; diff --git a/src/sqpack.rs b/src/sqpack.rs index 02dd13d..5ca16eb 100755 --- a/src/sqpack.rs +++ b/src/sqpack.rs @@ -1,10 +1,10 @@ use crate::compression::no_header_decompress; use crate::dat::{BlockHeader, CompressionMode}; use binrw::BinRead; -use crc::{Crc, CRC_32_JAMCRC}; use std::io::{Read, Seek, SeekFrom}; +use crate::crc::JAMCRC; -const JAMCRC: Crc = Crc::::new(&CRC_32_JAMCRC); +const CRC : JAMCRC = JAMCRC::new(); /// Calculates a hash for `index` files from a game path. pub fn calculate_hash(path: &str) -> u64 { @@ -14,8 +14,8 @@ pub fn calculate_hash(path: &str) -> u64 { let (directory, filename) = lowercase.split_at(pos); - let directory_crc = JAMCRC.checksum(directory.as_bytes()); - let filename_crc = JAMCRC.checksum(filename[1..filename.len()].as_bytes()); + let directory_crc = CRC.checksum(directory.as_bytes()); + let filename_crc = CRC.checksum(filename[1..filename.len()].as_bytes()); (directory_crc as u64) << 32 | (filename_crc as u64) }