Use a more safe way to patch BGI script

This commit is contained in:
2025-06-07 21:07:28 +08:00
parent f1e35c904c
commit 4068cc5a04
4 changed files with 45 additions and 9 deletions

View File

@@ -4,7 +4,11 @@ use clap::{ArgAction, ArgGroup, Parser, Subcommand};
/// Tools for export and import scripts
#[derive(Parser, Debug)]
#[clap(group = ArgGroup::new("encodingg").multiple(false), group = ArgGroup::new("output_encodingg").multiple(false), group = ArgGroup::new("archive_encodingg").multiple(false))]
#[command(version, about, long_about = None)]
#[command(
version,
about,
long_about = "Tools for export and import scripts\nhttps://github.com/lifegpc/msg-tool"
)]
pub struct Arg {
#[arg(short = 't', long, value_enum, global = true)]
/// Script type
@@ -80,6 +84,11 @@ pub struct Arg {
/// Duplicate same strings when importing into BGI scripts.
/// Enable this will cause BGI scripts to become very large.
pub bgi_import_duplicate: bool,
#[cfg(feature = "bgi")]
#[arg(long, action = ArgAction::SetTrue, global = true, alias = "bgi-no-append")]
/// Disable appending new strings to the end of BGI scripts.
/// Disable may cause BGI scripts broken.
pub bgi_disable_append: bool,
#[command(subcommand)]
/// Command
pub command: Command,

View File

@@ -1061,6 +1061,8 @@ fn main() {
escude_enum_scr: arg.escude_enum_scr.clone(),
#[cfg(feature = "bgi")]
bgi_import_duplicate: arg.bgi_import_duplicate,
#[cfg(feature = "bgi")]
bgi_disable_append: arg.bgi_disable_append,
};
match &arg.command {
args::Command::Export { input, output } => {

View File

@@ -54,6 +54,7 @@ pub struct BGIScript {
is_v1: bool,
offset: usize,
import_duplicate: bool,
append: bool,
}
impl std::fmt::Debug for BGIScript {
@@ -79,6 +80,7 @@ impl BGIScript {
is_v1: true,
offset,
import_duplicate: config.bgi_import_duplicate,
append: !config.bgi_disable_append,
})
} else {
let mut parser = V0Parser::new(data.to_ref());
@@ -91,6 +93,7 @@ impl BGIScript {
is_v1: false,
offset: 0,
import_duplicate: config.bgi_import_duplicate,
append: !config.bgi_disable_append,
})
}
}
@@ -203,9 +206,13 @@ impl Script for BGIScript {
let mut old_offset = 0;
let mut new_offset = 0;
let mut new_address_map = BTreeMap::new();
if self.append {
file.write_all(&self.data.data)?;
new_offset = self.data.data.len();
}
for (address, nmes) in str_map {
let bgi_str_old_offset = address + self.offset;
if old_offset < bgi_str_old_offset {
if !self.append && old_offset < bgi_str_old_offset {
file.write_all(&self.data.data[old_offset..bgi_str_old_offset])?;
new_offset += bgi_str_old_offset - old_offset;
old_offset = bgi_str_old_offset;
@@ -216,14 +223,26 @@ impl Script for BGIScript {
.as_bytes_with_nul()
.len();
let nmes = encode_string(encoding, &nmes, false)?;
file.write_all(&nmes)?;
file.write_u8(0)?; // null terminator
let new_address = new_offset - self.offset;
let write_to_original = self.append && nmes.len() + 1 <= old_str_len;
if write_to_original {
file.write_all_at(bgi_str_old_offset, &nmes)?;
file.write_u8_at(bgi_str_old_offset + nmes.len(), 0)?; // null terminator
} else {
file.write_all(&nmes)?;
file.write_u8(0)?; // null terminator
}
let new_address = if write_to_original {
bgi_str_old_offset - self.offset
} else {
new_offset - self.offset
};
new_address_map.insert(address, new_address);
old_offset += old_str_len;
new_offset += nmes.len() + 1; // +1 for null terminator
if !write_to_original {
new_offset += nmes.len() + 1; // +1 for null terminator
}
}
if old_offset < self.data.data.len() {
if !self.append && old_offset < self.data.data.len() {
file.write_all(&self.data.data[old_offset..])?;
}
for bgis in self.strings.iter() {
@@ -242,6 +261,10 @@ impl Script for BGIScript {
let mut cur_str = strs.next();
let mut old_offset = 0;
let mut new_offset = 0;
if self.append {
file.write_all(&self.data.data)?;
new_offset = self.data.data.len();
}
while let Some(curs) = cur_str {
if !curs.is_internal() {
if cur_mes.is_none() {
@@ -249,7 +272,7 @@ impl Script for BGIScript {
}
}
let bgi_str_old_offset = curs.address + self.offset;
if old_offset < bgi_str_old_offset {
if !self.append && old_offset < bgi_str_old_offset {
file.write_all(&self.data.data[old_offset..bgi_str_old_offset])?;
new_offset += bgi_str_old_offset - old_offset;
old_offset = bgi_str_old_offset;
@@ -314,7 +337,7 @@ impl Script for BGIScript {
for str in nstrs {
file.write_u32_at(str.offset, str.address as u32)?;
}
if old_offset < self.data.data.len() {
if !self.append && old_offset < self.data.data.len() {
file.write_all(&self.data.data[old_offset..])?;
}
Ok(())

View File

@@ -195,6 +195,8 @@ pub struct ExtraConfig {
pub escude_enum_scr: Option<String>,
#[cfg(feature = "bgi")]
pub bgi_import_duplicate: bool,
#[cfg(feature = "bgi")]
pub bgi_disable_append: bool,
}
#[derive(Clone, Copy, Debug, ValueEnum, PartialEq, Eq, PartialOrd, Ord)]