dref support load dpak from archive

This commit is contained in:
2025-07-31 15:06:15 +08:00
parent 644cdefe70
commit 8c565ad233
34 changed files with 735 additions and 621 deletions

View File

@@ -32,8 +32,11 @@ impl ScriptBuilder for DrefBuilder {
encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(Dref::new(buf, encoding, filename, config)?))
Ok(Box::new(Dref::new(
buf, encoding, filename, config, archive,
)?))
}
fn extensions(&self) -> &'static [&'static str] {
@@ -71,6 +74,16 @@ impl Dpak {
Ok(Self { psb })
}
pub fn load_from_data(data: &[u8]) -> Result<Self> {
let mut psb = PsbReader::open_psb(MemReaderRef::new(data))
.map_err(|e| anyhow::anyhow!("Failed to read PSB from DPAK data: {:?}", e))?;
let psb = psb
.load()
.map_err(|e| anyhow::anyhow!("Failed to load PSB from DPAK data: {:?}", e))?;
let psb = psb.to_psb_fixed();
Ok(Self { psb })
}
pub fn load_image(&self, name: &str) -> Result<(ImageData, Option<OffsetData>)> {
let root = self.psb.root();
let rid = root[name]
@@ -149,12 +162,31 @@ impl DpakLoader {
};
dpak.load_image(filename)
}
pub fn load_archives(&mut self, in_archives: &HashMap<String, Vec<u8>>) -> Result<()> {
for (name, data) in in_archives.iter() {
if !self.map.contains_key(name) {
let dpak = Dpak::load_from_data(data)?;
self.map.insert(name.clone(), dpak);
}
}
Ok(())
}
}
#[derive(Debug)]
pub struct Dref {
urls: Vec<Url>,
dir: PathBuf,
in_archives: HashMap<String, Vec<u8>>,
}
impl std::fmt::Debug for Dref {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("Dref")
.field("urls", &self.urls)
.field("dir", &self.dir)
.finish()
}
}
impl Dref {
@@ -163,6 +195,7 @@ impl Dref {
encoding: Encoding,
filename: &str,
_config: &ExtraConfig,
archive: Option<&Box<dyn Script>>,
) -> Result<Self> {
let text = decode_with_bom_detect(encoding, &buf, true)?.0;
let mut urls = Vec::new();
@@ -190,7 +223,25 @@ impl Dref {
));
}
}
Ok(Self { urls, dir })
let mut in_archives = HashMap::new();
if let Some(archive) = archive {
if archive.is_archive() {
for url in urls.iter() {
let filename = url.domain().ok_or(anyhow::anyhow!(
"Invalid URL in DREF file: {} (missing domain)",
url
))?;
if let Ok(mut content) = archive.open_file_by_name(filename, true) {
in_archives.insert(filename.to_string(), content.data()?);
}
}
}
}
Ok(Self {
urls,
dir,
in_archives,
})
}
}
@@ -209,6 +260,7 @@ impl Script for Dref {
fn export_image(&self) -> Result<ImageData> {
let mut loader = DpakLoader::default();
loader.load_archives(&self.in_archives)?;
let base_url = &self.urls[0];
let dpak = base_url.domain().ok_or(anyhow::anyhow!(
"Invalid URL in DREF file: {} (missing domain)",

View File

@@ -32,6 +32,7 @@ impl ScriptBuilder for PImgBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(PImg::new(MemReader::new(buf), filename, config)?))
}
@@ -42,6 +43,7 @@ impl ScriptBuilder for PImgBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
if filename == "-" {
let data = crate::utils::files::read_file(filename)?;
@@ -60,6 +62,7 @@ impl ScriptBuilder for PImgBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(PImg::new(reader, filename, config)?))
}

View File

@@ -26,6 +26,7 @@ impl ScriptBuilder for TlgImageBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(TlgImage::new(MemReader::new(data), config)?))
}

View File

@@ -31,6 +31,7 @@ impl ScriptBuilder for KsBuilder {
encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(KsScript::new(buf, encoding, config)?))
}

View File

@@ -25,6 +25,7 @@ impl ScriptBuilder for MdfBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
_config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(Mdf::new(buf, filename)?))
}

View File

@@ -32,6 +32,7 @@ impl ScriptBuilder for ScnScriptBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(ScnScript::new(
MemReader::new(buf),
@@ -46,6 +47,7 @@ impl ScriptBuilder for ScnScriptBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
if filename == "-" {
let data = crate::utils::files::read_file(filename)?;
@@ -68,6 +70,7 @@ impl ScriptBuilder for ScnScriptBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(ScnScript::new(reader, filename, config)?))
}

View File

@@ -26,6 +26,7 @@ impl ScriptBuilder for SimpleCryptBuilder {
_encoding: Encoding,
_archive_encoding: Encoding,
_config: &ExtraConfig,
_archive: Option<&Box<dyn Script>>,
) -> Result<Box<dyn Script>> {
Ok(Box::new(SimpleCrypt::new(buf, filename)?))
}