mirror of
https://github.com/lifegpc/msg-tool.git
synced 2026-06-07 13:28:47 +08:00
Add a option to dump debug info for xp3 archive
handle time prop in xp3 file entry Remove already processed hash file name
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
use super::consts::*;
|
||||
use super::crypt::Crypt;
|
||||
use crate::scripts::base::ReadSeek;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
/// Represents a single data segment for a file.
|
||||
@@ -35,6 +36,7 @@ pub struct Xp3Entry {
|
||||
pub file_hash: u32,
|
||||
pub original_size: u64,
|
||||
pub archived_size: u64,
|
||||
pub timestamp: Option<u64>,
|
||||
pub segments: Vec<Segment>,
|
||||
pub extras: Vec<ExtraProp>,
|
||||
}
|
||||
@@ -47,13 +49,50 @@ impl Xp3Entry {
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ExtraProp {
|
||||
pub tag: [u8; 4],
|
||||
pub tag: PropTag,
|
||||
pub data: Vec<u8>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct PropTag {
|
||||
tag: [u8; 4],
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for PropTag {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{:?}", bytes::Bytes::copy_from_slice(&self.tag))
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for PropTag {
|
||||
type Target = [u8; 4];
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.tag
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for PropTag {
|
||||
fn deref_mut(&mut self) -> &mut Self::Target {
|
||||
&mut self.tag
|
||||
}
|
||||
}
|
||||
|
||||
impl From<[u8; 4]> for PropTag {
|
||||
fn from(value: [u8; 4]) -> Self {
|
||||
PropTag { tag: value }
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<&[u8; 4]> for PropTag {
|
||||
fn eq(&self, other: &&[u8; 4]) -> bool {
|
||||
&self.tag == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtraProp {
|
||||
pub fn is_filename_hash(&self) -> bool {
|
||||
&self.tag == CHUNK_HNFN
|
||||
self.tag == CHUNK_HNFN
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pub const CHUNK_INFO: &[u8; 4] = b"info";
|
||||
pub const CHUNK_SEGM: &[u8; 4] = b"segm";
|
||||
pub const CHUNK_ADLR: &[u8; 4] = b"adlr";
|
||||
pub const CHUNK_HNFN: &[u8; 4] = b"hnfn";
|
||||
pub const CHUNK_TIME: &[u8; 4] = b"time";
|
||||
|
||||
// Index entry flags
|
||||
pub const TVP_XP3_INDEX_ENCODE_METHOD_MASK: u8 = 0x07;
|
||||
|
||||
@@ -26,6 +26,7 @@ pub fn default_init_crypt(archive: &mut Xp3Archive) -> Result<()> {
|
||||
filename_map.insert(hash, name);
|
||||
}
|
||||
}
|
||||
archive.extras.retain(|extra| !extra.is_filename_hash());
|
||||
for entry in &mut archive.entries {
|
||||
if let Some(name) = filename_map.get(&entry.file_hash) {
|
||||
entry.name = name.clone();
|
||||
|
||||
@@ -171,6 +171,9 @@ impl Xp3Archive {
|
||||
filename: &str,
|
||||
) -> Result<Self> {
|
||||
let mut archive = archive::Xp3Archive::new(stream, config, filename)?;
|
||||
if config.xp3_debug_archive {
|
||||
println!("Debug info for {}:\n{:#?}", filename, archive);
|
||||
}
|
||||
archive.entries.retain(|entry| {
|
||||
let i = &entry.name;
|
||||
!(i.find("$$$ This is a protected archive. $$$").is_some()
|
||||
|
||||
@@ -66,6 +66,7 @@ impl Xp3Archive {
|
||||
let mut file_hash = None;
|
||||
let mut original_size = None;
|
||||
let mut archived_size = None;
|
||||
let mut timestamp = None;
|
||||
let mut segments = Vec::new();
|
||||
let mut seg_offset = 0;
|
||||
let mut entry_extras = Vec::new();
|
||||
@@ -116,11 +117,16 @@ impl Xp3Archive {
|
||||
});
|
||||
seg_offset += original_size;
|
||||
}
|
||||
} else if &chunk_sig == CHUNK_TIME {
|
||||
if chunk_size == 8 {
|
||||
timestamp = Some(index_stream.read_u64()?);
|
||||
chunk_size -= 8;
|
||||
}
|
||||
} else {
|
||||
let data = index_stream.read_exact_vec(chunk_size as usize)?;
|
||||
chunk_size = 0;
|
||||
entry_extras.push(ExtraProp {
|
||||
tag: chunk_sig,
|
||||
tag: chunk_sig.into(),
|
||||
data,
|
||||
});
|
||||
}
|
||||
@@ -140,12 +146,16 @@ impl Xp3Archive {
|
||||
archived_size: archived_size.ok_or_else(|| {
|
||||
anyhow::anyhow!("Missing archived size chunk in file entry")
|
||||
})?,
|
||||
timestamp,
|
||||
segments,
|
||||
extras: entry_extras,
|
||||
});
|
||||
} else {
|
||||
let data = index_stream.read_exact_vec(size as usize)?;
|
||||
extras.push(ExtraProp { tag: sig, data });
|
||||
extras.push(ExtraProp {
|
||||
tag: sig.into(),
|
||||
data,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user