feat: search for existing base VHD in same directory

When only a delta .app is provided without the base, fsdecrypt now
scans the same directory for an existing base VHD matching the
game ID pattern ({game_id}_*_0.vhd) before giving up.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jujuforce
2026-03-22 16:40:18 +01:00
co-authored by Claude Opus 4.6
parent c896f362ba
commit 371abf4e32
+42 -6
View File
@@ -406,12 +406,48 @@ fn main() -> Result<()> {
continue;
}
let Some(base) = base else {
println!(
"WARNING: Delta VHD(s) found for {game_id} but no base (seq=0) VHD was extracted."
);
println!(" Provide the base .app file to enable automatic merging.");
continue;
// If no base was extracted in this run, search the same directory for an existing one
let found_base_path;
let base = match base {
Some(b) => b,
None => {
// Look for a VHD matching "{game_id}_*_0.vhd" in the same directory as the delta
let delta_dir = deltas[0]
.vhd_path
.parent()
.unwrap_or_else(|| Path::new("."));
let pattern_prefix = format!("{game_id}_");
let pattern_suffix = "_0.vhd";
found_base_path = std::fs::read_dir(delta_dir)?
.filter_map(|e| e.ok())
.map(|e| e.path())
.find(|p| {
let name = p.file_name().unwrap_or_default().to_string_lossy();
name.starts_with(&pattern_prefix) && name.ends_with(pattern_suffix)
});
match &found_base_path {
Some(path) => {
println!("Found existing base VHD: {}", path.display());
// Create a temporary ExtractedVhd to reference
&ExtractedVhd {
vhd_path: path.clone(),
sequence_number: 0,
game_id: game_id.clone(),
}
}
None => {
println!(
"WARNING: Delta VHD(s) found for {game_id} but no base (seq=0) VHD found."
);
println!(
" Provide the base .app file or place the base VHD in the same directory."
);
continue;
}
}
}
};
for delta in deltas {