msg_tool\scripts\kirikiri\archive\xp3/
pe.rs1use super::consts::*;
2use anyhow::Result;
3use memchr::memmem::find;
4use pelite::{PeFile, Wrap};
5
6pub fn get_base_offset<D: AsRef<[u8]> + ?Sized>(data: &D) -> Result<u64> {
7 let file = PeFile::from_bytes(data)?;
8 if let Some(rsrc) = file.section_headers().by_name(".rsrc") {
9 let bytes = file.get_section_bytes(rsrc)?;
10 if let Some(pos) = find(bytes, XP3_MAGIC) {
11 return Ok(rsrc.file_range().start as u64 + pos as u64);
12 }
13 }
14 let last_section_end = file
15 .section_headers()
16 .iter()
17 .map(|s| s.PointerToRawData + s.SizeOfRawData)
18 .max()
19 .unwrap_or_else(|| match file.optional_header() {
20 Wrap::T32(h) => h.SizeOfHeaders,
21 Wrap::T64(h) => h.SizeOfHeaders,
22 });
23 let aligned_offset = ((last_section_end + 0xF) & !0xF) as usize;
24 let data = data.as_ref();
25 if aligned_offset >= data.len() {
26 anyhow::bail!("No overlay for pe image.");
27 }
28 for i in (aligned_offset..(data.len() - 11)).step_by(0x10) {
29 if &data[i..i + 11] == XP3_MAGIC {
30 return Ok(i as u64);
31 }
32 }
33 anyhow::bail!("Failed to find xp3 file in pe file.")
34}