mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-07-08 01:31:53 +08:00
Now support to detect default path
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1573,6 +1573,7 @@ dependencies = [
|
||||
"serde_yaml_ng",
|
||||
"sha1",
|
||||
"sha2",
|
||||
"siphasher",
|
||||
"stylua",
|
||||
"tendril",
|
||||
"unicode-segmentation",
|
||||
|
||||
@@ -57,6 +57,7 @@ serde_json = "1"
|
||||
serde_yaml_ng = "0.10"
|
||||
sha1 = { version = "0.11", optional = true }
|
||||
sha2 = { version = "0.11", optional = true }
|
||||
siphasher = { version = "1.0", optional = true }
|
||||
stylua = { version = "2.1", optional = true, default-features = false}
|
||||
tendril = { version = "0.5", optional = true }
|
||||
unicode-segmentation = "1.12"
|
||||
@@ -101,7 +102,7 @@ hexen-haus = ["memchr", "utils-str"]
|
||||
hexen-haus-arc = ["hexen-haus"]
|
||||
hexen-haus-img = ["hexen-haus", "image"]
|
||||
kirikiri = ["emote-psb", "fancy-regex", "flate2", "json", "lz4", "utils-escape"]
|
||||
kirikiri-arc = ["kirikiri", "adler", "aes", "base64", "blake2", "bytes", "cbc", "chacha20/legacy", "fastcdc", "flate2", "hex", "int-enum", "md5", "msg_tool_macro/kirikiri-arc", "msg_tool_xp3data", "parse-size", "sha2", "utils-case-insensitive-string", "utils-lzss", "utils-serde-base64bytes", "utils-simple-pack", "zopfli", "zstd"]
|
||||
kirikiri-arc = ["kirikiri", "adler", "aes", "base64", "blake2", "bytes", "cbc", "chacha20/legacy", "fastcdc", "flate2", "hex", "int-enum", "md5", "msg_tool_macro/kirikiri-arc", "msg_tool_xp3data", "parse-size", "sha2", "siphasher", "utils-case-insensitive-string", "utils-lzss", "utils-serde-base64bytes", "utils-simple-pack", "zopfli", "zstd"]
|
||||
kirikiri-img = ["kirikiri", "image", "libtlg-rs"]
|
||||
musica = []
|
||||
musica-arc = ["musica", "crc32fast", "flate2", "include-flate", "utils-blowfish", "utils-rc4", "utils-serde-base64bytes", "utils-xored-stream"]
|
||||
|
||||
@@ -151,6 +151,20 @@
|
||||
"TpmFileName": "plugin/AmairoIsleNauts.tpm",
|
||||
"Title": "天色*アイルノーツ | 天色幻想岛"
|
||||
},
|
||||
"AMBITIOUS MISSION After Episode 1": {
|
||||
"$type": "HxCrypt",
|
||||
"Mask": 454,
|
||||
"Offset": 656,
|
||||
"PrologOrder": "AAEC",
|
||||
"OddBranchOrder": "BAMCBQAB",
|
||||
"EvenBranchOrder": "AAIHAwQBBgU=",
|
||||
"Key": "Wa7phHMk/a0hEztfLDpfcWbN1n7e0DYitcdCV1m/2EQ=",
|
||||
"Nonce": "DDEouJ4BezmeMVKZf7WVqA==",
|
||||
"FilterKey": 375708990042069900,
|
||||
"RandomType": 1,
|
||||
"ControlBlockName": "amb_after_ep1.bin",
|
||||
"Title": "AMBITIOUS MISSION アフターエピソード1 かぐや&あてな | Ambitious Mission FD1"
|
||||
},
|
||||
"Anata no Milk Kudasai na": {
|
||||
"$type": "HashCrypt",
|
||||
"Title": "あなたの精液くださいな ~私とボクとどっちがお好み?~"
|
||||
@@ -310,6 +324,67 @@
|
||||
"ControlBlockName": "cafe_stella.bin",
|
||||
"Title": "喫茶ステラと死神の蝶 | 星光咖啡馆与死神之蝶 | 星光咖啡館與死神之蝶"
|
||||
},
|
||||
"Café Stella to Shinigami no Chou [Steam]": {
|
||||
"$type": "HxCrypt",
|
||||
"Mask": 486,
|
||||
"Offset": 101,
|
||||
"PrologOrder": "AgAB",
|
||||
"OddBranchOrder": "BAEFAAMC",
|
||||
"EvenBranchOrder": "BgMBAgQFAAc=",
|
||||
"FilterKey": 9413765695581088110,
|
||||
"IndexKeyDict": {
|
||||
"data.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"video.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"bgm.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"fgimage.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"bgimage.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"scn.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"voice.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"main.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"evimage.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"uipsd.xp3": {
|
||||
"Key": "sd8wA9myXvbA4ATJnq6JYia3V5otV84MkuSiW4aYOog=",
|
||||
"Nonce": "HXJsNtEkHsOPDBcx/QODdQ=="
|
||||
},
|
||||
"video2.xp3": {
|
||||
"Key": "9lU4Kgw+IvRM3Zm0ubsa161RAxURD9ghXmSvYH7f/VE=",
|
||||
"Nonce": "r5eGhOPufNjqgZMwtggGhg=="
|
||||
},
|
||||
"adult.xp3": {
|
||||
"Key": "9lU4Kgw+IvRM3Zm0ubsa161RAxURD9ghXmSvYH7f/VE=",
|
||||
"Nonce": "r5eGhOPufNjqgZMwtggGhg=="
|
||||
}
|
||||
},
|
||||
"ControlBlockName": "cafe_stella_steam.bin",
|
||||
"Title": "喫茶ステラと死神の蝶 [Steam] | 星光咖啡馆与死神之蝶 [Steam] | 星光咖啡館與死神之蝶 [Steam]"
|
||||
},
|
||||
"CharaBration!": {
|
||||
"$type": "AkabeiCrypt",
|
||||
"Seed": 3854429322,
|
||||
@@ -420,7 +495,8 @@
|
||||
"Key": "4ozUw00nStHvknH8ECpqL1BVC9nOrpdryY4wHKtBTFE=",
|
||||
"Nonce": "pjhv8KmiW/gnbdoy6c5J6Q==",
|
||||
"FilterKey": 12271333071625965214,
|
||||
"ControlBlockName": "dc5.bin"
|
||||
"ControlBlockName": "dc5.bin",
|
||||
"Title": "D.C.5 ~ダ・カーポ5~ | 初音岛5 | D.C.5 Plus Happiness ~ダ・カーポ5~プラスハピネス | D.C.5 ~Da Capo 5~ Future Link | D.C.5 Future Link ~ダ・カーポ5~ フューチャーリンク | D.C.5 Sweet Happiness ~ダ・カーポ5~スイートハピネス"
|
||||
},
|
||||
"Deatte 5-fun wa Ore no Mono!": {
|
||||
"$type": "XorCrypt",
|
||||
|
||||
BIN
msg_tool_xp3data/cx_cb/amb_after_ep1.bin
Normal file
BIN
msg_tool_xp3data/cx_cb/amb_after_ep1.bin
Normal file
Binary file not shown.
BIN
msg_tool_xp3data/cx_cb/cafe_stella_steam.bin
Normal file
BIN
msg_tool_xp3data/cx_cb/cafe_stella_steam.bin
Normal file
Binary file not shown.
@@ -2111,7 +2111,7 @@ impl HxCrypt {
|
||||
index_key = Some(ind.clone())
|
||||
}
|
||||
let index_key = index_key.ok_or_else(|| anyhow::anyhow!("Can not find index key."))?;
|
||||
let (file_map, path_map) = if let Some(path) = file_list_path {
|
||||
let (file_map, mut path_map) = if let Some(path) = file_list_path {
|
||||
let data = std::fs::read(path)?;
|
||||
let data = decode_to_string(Encoding::Utf8, &data, true)?;
|
||||
Self::read_names(&data, s)?
|
||||
@@ -2128,6 +2128,10 @@ impl HxCrypt {
|
||||
(HashMap::new(), HashMap::new())
|
||||
}
|
||||
};
|
||||
let default_path_hash = calculate_path_hash("", "xp3hnp");
|
||||
if !path_map.contains_key(&default_path_hash) {
|
||||
path_map.insert(default_path_hash, String::new());
|
||||
}
|
||||
Ok(Self {
|
||||
base: CxEncryption::new_inner(
|
||||
base,
|
||||
@@ -2952,6 +2956,18 @@ fn create_garbage_filename_set(file_hash_salt: &str) -> HashSet<FileHash> {
|
||||
set
|
||||
}
|
||||
|
||||
fn calculate_path_hash(pathname: &str, path_hash_salt: &str) -> PathHash {
|
||||
use std::hash::Hasher;
|
||||
let mut hasher = siphasher::sip::SipHasher24::new();
|
||||
(pathname.to_lowercase() + path_hash_salt)
|
||||
.encode_utf16()
|
||||
.for_each(|b| {
|
||||
hasher.write(&b.to_le_bytes());
|
||||
});
|
||||
let data = hasher.finish().to_ne_bytes();
|
||||
PathHash(u64::from_be_bytes(data))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_filehash_deserialize() {
|
||||
assert_eq!(
|
||||
@@ -2965,3 +2981,15 @@ fn test_filehash_deserialize() {
|
||||
.unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calculate_path_hash() {
|
||||
assert_eq!(
|
||||
calculate_path_hash("", "xp3hnp"),
|
||||
PathHash::try_from("94d4a97c61498621").unwrap(),
|
||||
);
|
||||
assert_eq!(
|
||||
calculate_path_hash("scenario/scripts/", "xp3hnp"),
|
||||
PathHash::try_from("c81c19411c1a5e54").unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user