Skip to content

Commit

Permalink
Merge pull request #6 from jon-zu/jz/net-ws-img-loading
Browse files Browse the repository at this point in the history
Jz/net ws img loading
  • Loading branch information
jon-zu authored Nov 24, 2024
2 parents a4b438e + 32fea4e commit 192b831
Show file tree
Hide file tree
Showing 31 changed files with 541 additions and 81 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@


out


*.img
6 changes: 3 additions & 3 deletions crates/img-extractor/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0.81"
anyhow = "1.0.93"
glob = "0.3.1"
rayon = "1.10.0"
serde = "1.0.197"
serde_json = "1.0.115"
serde = "1.0.215"
serde_json = "1.0.133"
shroom-img = { version = "0.1.0", path = "../shroom-img" }
4 changes: 2 additions & 2 deletions crates/img-extractor/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ use std::{
use glob::glob;
use shroom_img::{crypto::ImgCrypto, reader::ImgReader, value::Object};

fn do_dump(path: impl AsRef<Path>, base: impl AsRef<Path>, crypto: &Arc<ImgCrypto>, out: &PathBuf) -> anyhow::Result<()> {
fn do_dump(path: impl AsRef<Path>, base: impl AsRef<Path>, crypto: &Arc<ImgCrypto>, out: &Path) -> anyhow::Result<()> {
let path = path.as_ref();
let file = BufReader::new(File::open(&path)?);
let file = BufReader::new(File::open(path)?);
let mut img = ImgReader::new(file, crypto.clone().into());
let obj = Object::from_reader(&mut img)?;

Expand Down
5 changes: 3 additions & 2 deletions crates/shroom-crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,6 @@ aes = "0.8"
cipher = { version = "0.4", features = ["block-padding"] }
rand = "0.8"
ofb = "0.6.1"
itoa = "1.0.10"
bytemuck = "1.14.0"
itoa = "1.0.13"
bytemuck = "1.20.0"
crc = "3.2.1"
172 changes: 172 additions & 0 deletions crates/shroom-crypto/src/crc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
use crc::{Crc, Digest};

/// CRC32 used for integrity checks(as in memory edits)
pub struct SCrc32 {
table: [u32; 256],
}

pub const POLY_INT: u32 = 0xDD10EE12 - 0x191;

impl Default for SCrc32 {
fn default() -> Self {
Self::new(POLY_INT)
}
}

const fn scrc32_table(poly: u32) -> [u32; 256] {
let mut table = [0; 256];
let mut i = 0;
while i < 256 {
let mut crc = i as u32;
let mut j = 0;
while j < 8 {
if crc & 1 != 0 {
crc = (crc >> 1) ^ poly;
} else {
crc >>= 1;
}
j += 1;
}
table[i] = crc;
i += 1;
}
table
}

impl SCrc32 {
pub const fn new(poly: u32) -> Self {
Self {
table: scrc32_table(poly),
}
}

fn update_inner<T: AsRef<[u8]>>(&self, mut crc: u32, data: T) -> u32 {
for &byte in data.as_ref() {
crc = self.table[((crc as u8) ^ byte) as usize] ^ (crc << 8);
}
crc
}

fn update_slice16(&self, mut crc: u32, data: &[u8]) -> u32 {
//TODO use slice into [u8; 16]
let mut chunks = data.chunks_exact(16);
for chunk in chunks.by_ref() {
crc = self.update_inner(crc, chunk);
}
let rem = chunks.remainder();
if !rem.is_empty() {
crc = self.update_inner(crc, rem);
}
crc
}

pub fn update(&self, crc: u32, data: &[u8]) -> u32 {
self.update_slice16(crc, data)
}

pub fn table(&self) -> &[u32; 256] {
&self.table
}
}

pub const CRC_32_SHROOM: crc::Algorithm<u32> = crc::Algorithm {
width: 32,
poly: 0x04c11db7,
init: 0x00000000,
refin: false,
refout: false,
xorout: 0,
check: 0x765e7680,
residue: 0xc704dd7b,
};

pub static SCRC32_INT: SCrc32 = SCrc32::new(POLY_INT);
pub static CRC32_GAME: Crc<u32> = Crc::<u32>::new(&CRC_32_SHROOM);

pub struct GameDigest<'a> {
inner: Digest<'a, u32>,
}

impl Default for GameDigest<'_> {
fn default() -> Self {
Self::new()
}
}

impl GameDigest<'_> {
pub fn new() -> Self {
Self {
inner: CRC32_GAME.digest(),
}
}

pub fn with(init: u32) -> Self {
Self {
inner: CRC32_GAME.digest_with_initial(init),
}
}

pub fn update(mut self, data: &[u8]) -> Self {
self.inner.update(data);
self
}

pub fn update_str(mut self, data: &str) -> Self {
self.inner.update(data.as_bytes());
self
}

pub fn update_i32(mut self, data: i32) -> Self {
self.inner.update(&data.to_le_bytes());
self
}

pub fn update_i64(mut self, data: i64) -> Self {
self.inner.update(&data.to_le_bytes());
self
}

pub fn update_u32(mut self, data: u32) -> Self {
self.inner.update(&data.to_le_bytes());
self
}

pub fn update_u64(mut self, data: u64) -> Self {
self.inner.update(&data.to_le_bytes());
self
}

pub fn update_u8(mut self, data: u8) -> Self {
self.inner.update(&[data]);
self
}

pub fn update_f32(mut self, data: f32) -> Self {
self.inner.update(&data.to_le_bytes());
self
}

pub fn update_f64(mut self, data: f64) -> Self {
self.inner.update(&data.to_le_bytes());
self
}

pub fn finalize(self) -> u32 {
self.inner.finalize()
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn crc() {
assert_eq!(
GameDigest::with(148854160).update_str("sp").finalize(),
367474251
);
assert_eq!(GameDigest::new().update_u32(95).finalize(), 0xC36FDB97);
assert_eq!(GameDigest::new().update_u32(270).finalize(), 954028113);
}
}
4 changes: 2 additions & 2 deletions crates/shroom-crypto/src/ig_cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ pub struct IgHasher<'ctx> {
ctx: &'ctx IgContext,
}

impl<'ctx> IgHasher<'ctx> {
impl IgHasher<'_> {
pub fn update(&mut self, data: &[u8]) {
self.state = data
.iter()
Expand All @@ -111,7 +111,7 @@ impl<'ctx> IgHasher<'ctx> {
}
}

impl<'ctx> Hasher for IgHasher<'ctx> {
impl Hasher for IgHasher<'_> {
fn write(&mut self, bytes: &[u8]) {
self.update(bytes);
}
Expand Down
1 change: 1 addition & 0 deletions crates/shroom-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
pub mod ig_cipher;
pub mod str;
pub mod version;
pub mod crc;

pub mod default_keys {
pub const DEFAULT_IG_SHUFFLE: &[u8; 256] = include_bytes!("default_keys/ig_shuffle.bin");
Expand Down
2 changes: 1 addition & 1 deletion crates/shroom-crypto/src/net/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ pub fn decode_header_no_crypt(
hdr: PacketHeader,
) ->u16 {
let v = HiLo32::from_le_bytes(hdr);
v.high as u16
v.high
}

pub fn encode_header(key: RoundKey, length: u16, ver: u16) -> PacketHeader {
Expand Down
6 changes: 3 additions & 3 deletions crates/shroom-img/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ glob = "0.3"
flate2 = { version = "1", features = ["zlib"] }
aes = "0.8"
anyhow = { version = "1" }
binrw = "0.13"
binrw = "0.14"
bytemuck = "1"
encoding_rs = "0.8"
indexmap = { version = "2", features = ["serde"] }
Expand All @@ -25,5 +25,5 @@ texpresso = "2"
uuid = { version = "1", features = ["v4"] }
shroom-crypto = { version = "0.1", path = "../shroom-crypto" }
arcstr = { version = "1", features = ["serde"] }
thiserror = "1"
bit-struct = "0.3"
thiserror = "2"
bit-struct = "0.3"
10 changes: 10 additions & 0 deletions crates/shroom-img/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,16 @@ impl ImgCrypto {
))
}

pub fn kms() -> Self {
Self::new(Some(
WzDataCipher::new_from_slices(
default_keys::wz::DEFAULT_WZ_AES_KEY,
&[0x45,0x50,0x33,0x01,0x45,0x50,0x33,0x01,0x45,0x50,0x33,0x01,0x45,0x50,0x33,0x01]
)
.unwrap(),
))
}

pub fn europe() -> Self {
Self::new(Some(
WzDataCipher::new_from_slices(
Expand Down
2 changes: 1 addition & 1 deletion crates/shroom-img/src/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl<'r, R> ReaderDataResolver<'r, R> {
}
}

impl<'r, R: ImgRead> DataResolver for ReaderDataResolver<'r, R> {
impl<R: ImgRead> DataResolver for ReaderDataResolver<'_, R> {
fn resolve_canvas_data(&mut self, hdr: &WzCanvasHeader, offset: u64) -> BinResult<&[u8]> {
self.buf.clear();
self.reader.read_canvas_data(offset, hdr, &mut self.buf)?;
Expand Down
6 changes: 3 additions & 3 deletions crates/shroom-img/src/json/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,11 +130,11 @@ impl Value {
crate::value::Value::U16(v) => Self::Integer(*v as i64),
crate::value::Value::I32(v) => Self::Integer(*v as i64),
crate::value::Value::U32(v) => Self::Integer(*v as i64),
crate::value::Value::I64(v) => Self::Integer(*v as i64),
crate::value::Value::I64(v) => Self::Integer(*v),
crate::value::Value::F32(v) => Self::Number(*v as f64),
crate::value::Value::F64(v) => Self::Number(*v as f64),
crate::value::Value::F64(v) => Self::Number(*v),
crate::value::Value::String(v) => Self::String(v.clone()),
crate::value::Value::Object(v) => Self::from_img_value(ctx, &v),
crate::value::Value::Object(v) => Self::from_img_value(ctx, v),
}
}
pub fn from_property(ctx: &mut ValueDecodeCtx, v: &crate::value::Property) -> Property {
Expand Down
14 changes: 6 additions & 8 deletions crates/shroom-img/src/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,7 @@ use std::{
};

use crate::{
canvas::{WzCanvasHeader, WzCanvasLen, WzCanvasPropHeader},
data::{Data, OwnedReaderDataResolver, ReaderDataResolver},
error::ImgError,
sound::WzSound,
ty::WzInt,
util::BufReadExt,
Convex2, ImgContext, Link, PropertyValue, Vec2,
canvas::{WzCanvasHeader, WzCanvasLen, WzCanvasPropHeader}, crypto::ImgCrypto, data::{Data, OwnedReaderDataResolver, ReaderDataResolver}, error::ImgError, sound::WzSound, ty::WzInt, util::{chunked::ChunkedReader, BufReadExt}, Convex2, ImgContext, Link, PropertyValue, Vec2
};
use crate::{
str_table::{OffsetStrTable, ReadStrCtx},
Expand Down Expand Up @@ -171,7 +165,11 @@ impl<R: ImgRead> ImgReader<R> {
self.r.seek(std::io::SeekFrom::Start(offset))?;
let (_, len) = self.read_canvas_len()?;
let mut limited = (&mut self.r).take(len.data_len() as u64);
limited

let eu_crypto = ImgCrypto::europe();
let mut chunked = ChunkedReader::new(&mut limited, &eu_crypto);

chunked
.decompress_flate_size_to(w, hdr.txt_data_size() as u64)
.map_err(|err| ImgError::DecompressionFailed(offset, err).binrw_error(&mut self.r))?;

Expand Down
6 changes: 3 additions & 3 deletions crates/shroom-img/src/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ pub struct WzF32(

pub struct WzStrRef8<'a>(pub &'a [u8]);

impl<'s> BinWrite for WzStrRef8<'s> {
impl BinWrite for WzStrRef8<'_> {
type Args<'a> = &'a ImgCrypto;

fn write_options<W: Write + Seek>(
Expand All @@ -145,7 +145,7 @@ impl<'s> BinWrite for WzStrRef8<'s> {

pub struct WzStrRef16<'a>(pub &'a [u16]);

impl<'s> BinWrite for WzStrRef16<'s> {
impl BinWrite for WzStrRef16<'_> {
type Args<'a> = &'a ImgCrypto;

fn write_options<W: Write + Seek>(
Expand All @@ -170,7 +170,7 @@ impl<'s> BinWrite for WzStrRef16<'s> {
/// String reference for faster writing
pub struct WzStrRef<'a>(pub &'a str);

impl<'s> BinWrite for WzStrRef<'s> {
impl BinWrite for WzStrRef<'_> {
type Args<'a> = &'a ImgCrypto;

fn write_options<W: Write + Seek>(
Expand Down
7 changes: 3 additions & 4 deletions crates/shroom-img/src/util/chunked.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ impl<'a, R: Read> ChunkedReader<'a, R> {
}
}

impl<'a, R: Read> Read for ChunkedReader<'a, R> {
impl<R: Read> Read for ChunkedReader<'_, R> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
let n = self.refill_buf()?.min(buf.len());
let ix = self.ix;
Expand All @@ -142,7 +142,7 @@ impl<'a, R: Read> Read for ChunkedReader<'a, R> {
}
}

impl<'a, R: Read> BufRead for ChunkedReader<'a, R> {
impl<R: Read> BufRead for ChunkedReader<'_, R> {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
let n = self.refill_buf()?;
let ix = self.ix;
Expand All @@ -155,7 +155,6 @@ impl<'a, R: Read> BufRead for ChunkedReader<'a, R> {
}
}


#[cfg(test)]
mod tests {
use std::io::{Cursor, Seek};
Expand Down Expand Up @@ -234,4 +233,4 @@ mod tests {
let data = r.bytes().collect::<Result<Vec<_>, _>>().unwrap();
assert_eq!(data, ONES);
}
}
}
Loading

0 comments on commit 192b831

Please sign in to comment.