From 2179094303e4dbd127b17c2e08ad6c30efa11df2 Mon Sep 17 00:00:00 2001 From: lifegpc Date: Fri, 10 Apr 2026 10:26:09 +0800 Subject: [PATCH] Add HibikiCrypt (untested) --- msg_tool_xp3data/crypt.json | 4 ++++ src/scripts/kirikiri/archive/xp3/crypt/mod.rs | 24 +++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/msg_tool_xp3data/crypt.json b/msg_tool_xp3data/crypt.json index cbb1f07..55f8d4e 100644 --- a/msg_tool_xp3data/crypt.json +++ b/msg_tool_xp3data/crypt.json @@ -1137,6 +1137,10 @@ "ControlBlockName": "love_laby.bin", "Title": "らぶ+らび" }, + "LOVELY x CATION": { + "$type": "HibikiCrypt", + "Title": "LOVELY×CATION" + }, "Lovesick Puppies -Bokura wa Koi Suru Tame ni Umaretekita-": { "$type": "AppliqueCrypt", "Title": "LOVESICK PUPPIES -僕らは恋するために生まれてきた- | LOVESICK PUPPIES -我们为了恋爱而诞生-" diff --git a/src/scripts/kirikiri/archive/xp3/crypt/mod.rs b/src/scripts/kirikiri/archive/xp3/crypt/mod.rs index 180de1b..e2f7e21 100644 --- a/src/scripts/kirikiri/archive/xp3/crypt/mod.rs +++ b/src/scripts/kirikiri/archive/xp3/crypt/mod.rs @@ -170,10 +170,12 @@ enum CryptType { AppliqueCrypt, TokidokiCrypt, SourireCrypt, + HibikiCrypt, } #[derive(Clone, Debug, Deserialize)] #[serde(rename_all = "PascalCase")] +#[allow(dead_code)] pub struct BaseSchema { #[serde(default)] hash_after_crypt: bool, @@ -266,6 +268,7 @@ impl Schema { CryptType::AppliqueCrypt => Box::new(AppliqueCrypt::new(self.base.clone())), CryptType::TokidokiCrypt => Box::new(TokidokiCrypt::new(self.base.clone())), CryptType::SourireCrypt => Box::new(SourireCrypt::new(self.base.clone())), + CryptType::HibikiCrypt => Box::new(HibikiCrypt::new(self.base.clone())), }) } } @@ -1048,6 +1051,27 @@ impl Read for SourireCryptReader { } } +seek_crypt_filehash_key_impl!(HibikiCrypt, HibikiCryptReader); + +impl Read for HibikiCryptReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let readed = self.inner.read(buf)?; + let key1 = (self.key >> 5) as u8; + let key2 = (self.key >> 8) as u8; + for (i, t) in (&mut buf[..readed]).iter_mut().enumerate() { + let offset = self.seg_start + self.pos + i as u64; + let key = if offset <= 0x64 || offset & 4 != 0 { + key1 + } else { + key2 + }; + *t ^= key; + } + self.pos += readed as u64; + Ok(readed) + } +} + #[test] fn test_deserialize_crypt() { for (key, schema) in CRYPT_SCHEMA.iter() {