Use msg_tool_xp3data package to store xp3 data

This commit is contained in:
2026-04-08 09:40:29 +08:00
parent 6f6d76e5a9
commit 0fbe9cedbc
74 changed files with 99 additions and 28 deletions

10
Cargo.lock generated
View File

@@ -1438,8 +1438,8 @@ dependencies = [
"memchr",
"mozjpeg",
"msg-tool-jpegxl-sys",
"msg_tool_build",
"msg_tool_macro",
"msg_tool_xp3data",
"num_cpus",
"overf",
"parse-size",
@@ -1479,6 +1479,14 @@ dependencies = [
"syn 2.0.117",
]
[[package]]
name = "msg_tool_xp3data"
version = "0.3.1"
dependencies = [
"msg_tool_build",
"zstd",
]
[[package]]
name = "nasm-rs"
version = "0.3.2"

View File

@@ -38,6 +38,7 @@ markup5ever_rcdom = { version = "0.38", optional = true }
memchr = { version = "2.7", optional = true }
mozjpeg = { version = "0.10", optional = true }
msg_tool_macro = { path = "./msg_tool_macro" }
msg_tool_xp3data = { path = "./msg_tool_xp3data", optional = true }
num_cpus = "1.17"
overf = "0.1"
parse-size = { version = "1.1", optional = true }
@@ -93,7 +94,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", "bytes", "fastcdc", "flate2", "include-flate", "int-enum", "msg_tool_build/kirikiri-arc", "parse-size", "sha2", "utils-serde-base64bytes", "utils-simple-pack", "zopfli", "zstd"]
kirikiri-arc = ["kirikiri", "adler", "bytes", "fastcdc", "flate2", "int-enum", "msg_tool_xp3data", "parse-size", "sha2", "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"]
@@ -115,7 +116,7 @@ image-jxl = ["image", "jpegxl-sys"]
image-webp = ["webp"]
lossless-audio = ["utils-pcm"]
audio-flac = ["libflac-sys", "utils-pcm"]
unstable = ["msg_tool_macro/unstable"]
unstable = ["msg_tool_macro/unstable", "msg_tool_xp3data?/unstable"]
jieba = ["jieba-rs"]
emote-psb = ["dep:emote-psb", "adler", "lz4"]
# utils feature
@@ -136,5 +137,4 @@ utils-xored-stream = []
windows-sys = { version = "0.61", features = ["Win32_Globalization", "Win32_System_Diagnostics_Debug"] }
[build-dependencies]
msg_tool_build = { path = "./msg_tool_build", optional = true }
parse-size = "1.1"

View File

@@ -10,18 +10,4 @@ fn main() {
println!("cargo:rustc-link-arg=/STACK:{}", stack_size);
#[cfg(target_env = "gnu")]
println!("cargo:rustc-link-arg=-Wl,-z,stack-size={}", stack_size);
#[cfg(feature = "kirikiri-arc")]
{
let source_dir = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let crypt_json_path = source_dir.join("src/scripts/kirikiri/archive/xp3/crypt.json");
let outdir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
let level = std::env::var("MSG_TOOL_KIRIKIRI_ARC_GEN_LEVEL").unwrap_or("22".to_string());
println!("cargo:rerun-if-env-changed=OUT_DIR");
println!("cargo:rerun-if-changed={}", crypt_json_path.display());
let level = level
.parse::<i32>()
.expect("MSG_TOOL_KIRIKIRI_ARC_GEN_LEVEL must be a valid integer");
println!("cargo:rerun-if-env-changed=MSG_TOOL_KIRIKIRI_ARC_GEN_LEVEL");
msg_tool_build::kr_arc::gen_cx_cb(&crypt_json_path, &outdir, level).unwrap();
}
}

View File

@@ -11,8 +11,9 @@ json = { version = "0.12", optional = true }
zstd = { version = "0.13", optional = true }
[features]
kirikiri-arc = ["json", "simple-pack"]
kirikiri-arc = ["json", "simple-pack", "zstd"]
simple-pack = ["zstd"]
unstable = []
[package.metadata.docs.rs]
all-features = true

View File

@@ -1,6 +1,26 @@
use crate::simple_pack::SimplePack;
use std::path::Path;
/// Generate crypt.json.zst from crypt.json with minimum format
pub fn gen_crypt<P: AsRef<Path> + ?Sized, D: AsRef<Path> + ?Sized>(
json_path: &P,
outdir: &D,
level: i32,
) -> std::io::Result<()> {
let p = json_path.as_ref();
let json_data = std::fs::read_to_string(p)?;
let json = json::parse(&json_data)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
let out_data = json::stringify(json);
let out_path = outdir.as_ref().join("crypt.json.zst");
let mut out_file = std::io::BufWriter::new(std::fs::File::create(out_path)?);
let level = if level >= 0 && level <= 22 { level } else { 22 };
let mut encoder = zstd::stream::write::Encoder::new(&mut out_file, level)?;
std::io::copy(&mut out_data.as_bytes(), &mut encoder)?;
encoder.finish()?;
Ok(())
}
/// Pack all binary files in cx_cb into a single archive.
pub fn gen_cx_cb<P: AsRef<Path> + ?Sized, D: AsRef<Path> + ?Sized>(
json_path: &P,
@@ -8,11 +28,7 @@ pub fn gen_cx_cb<P: AsRef<Path> + ?Sized, D: AsRef<Path> + ?Sized>(
level: i32,
) -> std::io::Result<()> {
let p = json_path.as_ref();
let pb = p
.parent()
.unwrap_or_else(|| Path::new(""))
.join("crypt")
.join("cx_cb");
let pb = p.parent().unwrap_or_else(|| Path::new("")).join("cx_cb");
let json_data = std::fs::read_to_string(p)?;
let json = json::parse(&json_data)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;

View File

@@ -1,3 +1,4 @@
#![cfg_attr(any(docsrs, feature = "unstable"), feature(doc_cfg))]
#[cfg(feature = "kirikiri-arc")]
pub mod kr_arc;
#[cfg(feature = "simple-pack")]

2
msg_tool_xp3data/.gitignore vendored Normal file
View File

@@ -0,0 +1,2 @@
Cargo.lock
target/

View File

@@ -0,0 +1,22 @@
[package]
name = "msg_tool_xp3data"
version = "0.3.1"
edition = "2024"
repository = "https://github.com/lifegpc/msg-tool"
description = "XP3 data for the msg-tool project."
license = "GPL-3.0-or-later"
[lib]
path = "lib.rs"
[dependencies]
zstd = "0.13"
[features]
unstable = ["msg_tool_build/unstable"]
[package.metadata.docs.rs]
all-features = true
[build-dependencies]
msg_tool_build = { path = "../msg_tool_build", features = ["kirikiri-arc"] }

23
msg_tool_xp3data/build.rs Normal file
View File

@@ -0,0 +1,23 @@
fn main() {
let source_dir = std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
let crypt_json_path = source_dir.join("crypt.json");
let outdir = std::path::PathBuf::from(std::env::var("OUT_DIR").unwrap());
let level = std::env::var("MSG_TOOL_KIRIKIRI_ARC_GEN_LEVEL").unwrap_or("22".to_string());
println!("cargo:rerun-if-env-changed=OUT_DIR");
println!("cargo:rerun-if-changed={}", crypt_json_path.display());
println!(
"cargo:rerun-if-changed={}",
source_dir.join("cx_cb").display()
);
let level = level
.parse::<i32>()
.expect("MSG_TOOL_KIRIKIRI_ARC_GEN_LEVEL must be a valid integer");
println!("cargo:rerun-if-env-changed=MSG_TOOL_KIRIKIRI_ARC_GEN_LEVEL");
msg_tool_build::kr_arc::gen_cx_cb(&crypt_json_path, &outdir, level).unwrap();
let level = std::env::var("MSG_TOOL_KIRIKIRI_CRYPT_COMPRESS_LEVEL").unwrap_or("22".to_string());
let level = level
.parse::<i32>()
.expect("MSG_TOOL_KIRIKIRI_CRYPT_COMPRESS_LEVEL must be a valid integer");
println!("cargo:rerun-if-env-changed=MSG_TOOL_KIRIKIRI_CRYPT_COMPRESS_LEVEL");
msg_tool_build::kr_arc::gen_crypt(&crypt_json_path, &outdir, level).unwrap();
}

14
msg_tool_xp3data/lib.rs Normal file
View File

@@ -0,0 +1,14 @@
#![cfg_attr(any(docsrs, feature = "unstable"), feature(doc_cfg))]
use std::io::Read;
/// Control Block data for CxEncryption packed with SimplePack.
pub const CX_CB_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/cx_cb.pck"));
const CRYPT_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/crypt.json.zst"));
/// Get the crypt.json data as a string.
pub fn get_crypt_data() -> String {
let mut decoder = zstd::stream::read::Decoder::new(CRYPT_DATA).unwrap();
let mut out = String::new();
decoder.read_to_string(&mut out).unwrap();
out
}

View File

@@ -8,6 +8,7 @@ use crate::utils::encoding::*;
use crate::utils::serde_base64bytes::*;
use crate::utils::simple_pack::*;
use anyhow::Result;
use msg_tool_xp3data::*;
use serde::Deserialize;
use std::collections::{BTreeMap, HashMap};
use std::io::{Read, Seek, SeekFrom};
@@ -162,12 +163,9 @@ impl Schema {
}
}
include_flate::flate!(static CRYPT_DATA: str from "src/scripts/kirikiri/archive/xp3/crypt.json" with zstd);
const CX_CB_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/cx_cb.pck"));
lazy_static::lazy_static! {
static ref CRYPT_SCHEMA: BTreeMap<String, Schema> = {
serde_json::from_str(&CRYPT_DATA).expect("Failed to parse crypt.json")
serde_json::from_str(&get_crypt_data()).expect("Failed to parse crypt.json")
};
static ref ALIAS_TABLE: HashMap<String, String> = {
let mut table = HashMap::new();