diff --git a/msg_tool_xp3data/crypt.json b/msg_tool_xp3data/crypt.json index 856e354..e9b121e 100644 --- a/msg_tool_xp3data/crypt.json +++ b/msg_tool_xp3data/crypt.json @@ -135,6 +135,10 @@ "$type": "HashCrypt", "Title": "姉撮 ~堕ちていくお姉ちゃんを助けられない僕~" }, + "Aniki No Yome-san nara": { + "$type": "PoringSoftCrypt", + "Title": "兄貴の嫁さんなら、俺にハメられてヒイヒイ言ってるところだよ" + }, "Aqua": { "$type": "CxEncryption", "Mask": 424, @@ -191,6 +195,10 @@ "$type": "HashCrypt", "Title": "ビッチギャルのガチイキアクメ ~家庭教師の童貞巨根にハマり堕ち~ | Bitch Gyaru no Gachi Iki Acme" }, + "blue note": { + "$type": "PoringSoftCrypt", + "Title": "ブルーノート" + }, "Bodatsu ~Kindan no Shokushu Soukan~": { "$type": "HashCrypt", "Title": "母奪~禁断の触手相姦~" @@ -205,6 +213,10 @@ "Key": 49, "Title": "僕の未来は、恋と課金と。~Charge To The Future~ [体験版] | 我的未来是恋爱与氪金 [试用版]" }, + "Bra-ban!": { + "$type": "PoringSoftCrypt", + "Title": "ぶらばん! | 管乐恋曲!" + }, "Café Stella to Shinigami no Chou": { "$type": "RiddleCxCrypt", "Mask": 622, @@ -743,6 +755,10 @@ "$type": "NatsupochiCrypt", "Title": "妹孕ませっくす" }, + "Imouto Kairaku Ochi": { + "$type": "PoringSoftCrypt", + "Title": "妹快楽堕ち~お兄ちゃんに無理やりハメられてから~ | 沉溺快感中的妹妹~自从被哥哥强行插入后~" + }, "Imouto Shokushu Rape": { "$type": "HashCrypt", "Title": "妹触手レイプ ~復讐の処女貫通~" @@ -1084,6 +1100,10 @@ "$type": "DieselmineCrypt", "Title": "M-days 慟哭の交尾地獄" }, + "Mahara Miko": { + "$type": "PoringSoftCrypt", + "Title": "魔孕巫女~お清めは愛欲淫靡に~" + }, "Mahoutsukai no Yoru": { "$type": "CxEncryption", "Mask": 554, @@ -1214,6 +1234,10 @@ "$type": "HashCrypt", "Title": "桃尻インストラクター寝取りレッスン ~競泳水着でえろざんまい~" }, + "Muchimuchi Dekapai Mara Gui Maou-sama": { + "$type": "PoringSoftCrypt", + "Title": "ムチムチデカパイマラ喰い魔王様とおんぼろ四畳半同棲生活 | 与爆乳魔王的同居生活" + }, "Mugen no Tír na nÓg": { "$type": "XorCrypt", "Key": 85, @@ -1227,6 +1251,10 @@ "$type": "HashCrypt", "Title": "軟体レッスン ~いいなり彼女とひみつの放課後~" }, + "Nariyuki→Papakatsu Girls!!": { + "$type": "PoringSoftCrypt", + "Title": "なりゆき→パパ活GIRLS!! | 惠里和千寻的援交日记" + }, "Natsu no Owari": { "$type": "XorCrypt", "Key": 87, @@ -1236,6 +1264,10 @@ "$type": "NatsupochiCrypt", "Title": "夏色姉妹 ~幼馴染と真夏のヒメゴト~ | 夏色姐妹~青梅竹马与盛夏秘事~" }, + "Natsuiro Shimai Trial": { + "$type": "PoringSoftCrypt", + "Title": "夏色姉妹 ~幼馴染と真夏のヒメゴト~ 体験版" + }, "Natsupochi": { "$type": "NatsupochiCrypt", "Title": "なつぽち" @@ -1311,6 +1343,10 @@ "$type": "OkibaCrypt", "Title": "置き場がない!" }, + "Oku-sama wa Moto Yariman -Besluted-": { + "$type": "PoringSoftCrypt", + "Title": "奥様は元ヤリマン ―Besluted―" + }, "Omae no Kaa-chan, Ii Onna Da yo na": { "$type": "NatsupochiCrypt", "Title": "お前の母ちゃん、良い女だよな。 | 你妈真漂亮 | 你媽真漂亮" @@ -1471,6 +1507,9 @@ "EvenBranchOrder": "BAYBBQIHAAM=", "ControlBlockName": "pendulum.bin" }, + "PRICE": { + "$type": "PoringSoftCrypt" + }, "Princess Saga": { "$type": "FlyingShineCrypt", "Title": "プリンセスサーガ" @@ -1546,6 +1585,10 @@ "EvenBranchOrder": "BgQFAAIHAQM=", "ControlBlockName": "riddle_steam.bin" }, + "Riding Incubus": { + "$type": "PoringSoftCrypt", + "Title": "らいでぃんぐ いんきゅばす" + }, "Rui wa Tomo o Yobu": { "$type": "CxEncryption", "Mask": 740, @@ -1679,6 +1722,10 @@ "$type": "FlyingShineCrypt", "Title": "親友の巨乳ママと中出し性活~こんなに射精してちゃ孕んじゃったね" }, + "Shindan no Kekka, Sore wa Koi no Yamai Desu": { + "$type": "PoringSoftCrypt", + "Title": "診断の結果、それは恋の病です | 诊断的结果、那是名为恋爱的病" + }, "Shiniyuku Kimi, Yakata ni Mebuku Zouo": { "$type": "CxEncryption", "Mask": 379, @@ -1896,6 +1943,10 @@ "ControlBlockName": "towazugatari.bin", "Title": "永遠ズ語リ~少女凌辱秘抄~" }, + "Tsubasa no Oka no Hime": { + "$type": "PoringSoftCrypt", + "Title": "つばさの丘の姫王 A red and blue moon -finite loop-" + }, "Tsuma Kai -Tsuma Gai-": { "$type": "FlyingShineCrypt", "Title": "貸し出し妻、満里奈の“ネトラセ”報告 外伝1 ―女子校生、満里奈の性感開発―" diff --git a/src/args.rs b/src/args.rs index 2dcaf66..bfd55a9 100644 --- a/src/args.rs +++ b/src/args.rs @@ -732,6 +732,11 @@ pub struct Arg { #[arg(long, global = true)] /// Force extract encrypted files in Kirikiri XP3 archive without decryption. pub xp3_force_extract: bool, + #[cfg(feature = "kirikiri-arc")] + #[arg(long, global = true, visible_alias = "xp3-fd")] + /// Force decrypt files in Kirikiri xp3 archive even when flags are not set. + /// Some encrypted files in Kirikiri XP3 archive may not set encryption flag, but still encrypted. Enable this to force decrypt these files. + pub xp3_force_decrypt: bool, #[command(subcommand)] /// Command pub command: Command, diff --git a/src/main.rs b/src/main.rs index c478a25..f3f6c31 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3397,6 +3397,8 @@ fn main() { xp3_debug_archive: arg.xp3_debug_archive, #[cfg(feature = "kirikiri-arc")] xp3_force_extract: arg.xp3_force_extract, + #[cfg(feature = "kirikiri-arc")] + xp3_force_decrypt: arg.xp3_force_decrypt, }); match &arg.command { args::Command::Export { input, output } => { diff --git a/src/scripts/kirikiri/archive/xp3/crypt/mod.rs b/src/scripts/kirikiri/archive/xp3/crypt/mod.rs index 5bc1d7b..37f3803 100644 --- a/src/scripts/kirikiri/archive/xp3/crypt/mod.rs +++ b/src/scripts/kirikiri/archive/xp3/crypt/mod.rs @@ -165,6 +165,7 @@ enum CryptType { NephriteCrypt, AlteredPinkCrypt, NatsupochiCrypt, + PoringSoftCrypt, } #[derive(Clone, Debug, Deserialize)] @@ -257,6 +258,7 @@ impl Schema { CryptType::NephriteCrypt => Box::new(NephriteCrypt::new(self.base.clone())), CryptType::AlteredPinkCrypt => Box::new(AlteredPinkCrypt::new(self.base.clone())), CryptType::NatsupochiCrypt => Box::new(NatsupochiCrypt::new(self.base.clone())), + CryptType::PoringSoftCrypt => Box::new(PoringSoftCrypt::new(self.base.clone())), }) } } @@ -910,6 +912,20 @@ impl Read for NatsupochiCryptReader { } } +seek_crypt_filehash_key_impl!(PoringSoftCrypt, PoringSoftCryptReader); + +impl Read for PoringSoftCryptReader { + fn read(&mut self, buf: &mut [u8]) -> std::io::Result { + let readed = self.inner.read(buf)?; + let key = (!w!(self.key + 1)) as u8; + for t in (&mut buf[..readed]).iter_mut() { + *t ^= key; + } + self.pos += readed as u64; + Ok(readed) + } +} + #[test] fn test_deserialize_crypt() { for (key, schema) in CRYPT_SCHEMA.iter() { diff --git a/src/scripts/kirikiri/archive/xp3/mod.rs b/src/scripts/kirikiri/archive/xp3/mod.rs index 18bdc5d..a748594 100644 --- a/src/scripts/kirikiri/archive/xp3/mod.rs +++ b/src/scripts/kirikiri/archive/xp3/mod.rs @@ -163,6 +163,7 @@ pub struct Xp3Archive { decrypt_simple_crypt: bool, decompress_mdf: bool, force_extract: bool, + force_decrypt: bool, } impl Xp3Archive { @@ -189,6 +190,7 @@ impl Xp3Archive { decrypt_simple_crypt: config.xp3_simple_crypt, decompress_mdf: config.xp3_mdf_decompress, force_extract: config.xp3_force_extract, + force_decrypt: config.xp3_force_decrypt, }) } } @@ -240,6 +242,7 @@ impl Script for Xp3Archive { self.archive.base_offset, crypt, skip_decrypt, + self.force_decrypt, ); let mut header = [0u8; 16]; let header_len = entry.read(&mut header)?; @@ -314,6 +317,7 @@ struct Entry { entries_pos: Vec, script_type: Option, skip_decrypt: bool, + force_decrypt: bool, } #[automatically_derived] @@ -341,6 +345,7 @@ impl Entry { base_offset: u64, crypt: Arc>, skip_decrypt: bool, + force_decrypt: bool, ) -> Self { let mut pos = 0; let entries_pos = index @@ -363,6 +368,7 @@ impl Entry { crypt, crypt_stream: None, skip_decrypt, + force_decrypt, } } } @@ -419,7 +425,7 @@ impl Read for Entry { let seg_pos = self.entries_pos[seg_index]; let skip_pos = self.pos - seg_pos; let read_size = seg.archived_size; - if !self.skip_decrypt && self.index.is_encrypted() { + if !self.skip_decrypt && (self.index.is_encrypted() || self.force_decrypt) { if seg.is_compressed || !self.crypt.decrypt_seek_supported() { let mut cache: Box = if seg.is_compressed { let mut inner = diff --git a/src/types.rs b/src/types.rs index f97ebbe..e0efa82 100644 --- a/src/types.rs +++ b/src/types.rs @@ -645,6 +645,10 @@ pub struct ExtraConfig { #[cfg(feature = "kirikiri-arc")] /// Force extract encrypted files in Kirikiri XP3 archive without decryption. pub xp3_force_extract: bool, + #[cfg(feature = "kirikiri-arc")] + /// Force decrypt files in Kirikiri xp3 archive even when flags are not set. + /// Some encrypted files in Kirikiri XP3 archive may not set encryption flag, but still encrypted. Enable this to force decrypt these files. + pub xp3_force_decrypt: bool, } #[cfg(feature = "artemis")]