diff --git a/examples/list_files.rs b/examples/list_files.rs index ce4185d..dfc73b4 100644 --- a/examples/list_files.rs +++ b/examples/list_files.rs @@ -28,6 +28,9 @@ fn main() -> Result<(), Error> { let source_iso = iso::IsoReader::read(BufReader::new(source_iso_file)) .context("error reading source ISO")?; + println!("{:?}", source_iso.volume_descriptor); + println!("max used size: {}", source_iso.get_max_used_prefix_size()); + print_dir(String::new(), &source_iso.directory_table); Ok(()) diff --git a/src/bin/iso2god.rs b/src/bin/iso2god.rs index 0e40d60..6bc05ab 100644 --- a/src/bin/iso2god.rs +++ b/src/bin/iso2god.rs @@ -33,6 +33,10 @@ struct Cli { /// Set game title #[arg(long)] game_title: Option, + + /// Trim off unused space from the ISO image + #[arg(long)] + trim: bool, } fn main() -> Result<(), Error> { @@ -67,22 +71,26 @@ fn main() -> Result<(), Error> { .execution_info .context("no execution info in default.xex header")?; - if args.dry_run { + { let title_id = hex::encode_upper(exe_info.title_id); let name = game_list::find_title_by_id(exe_info.title_id).unwrap_or("(unknown)".to_owned()); println!("Title ID: {title_id}"); println!(" Name: {name}"); + } + if args.dry_run { return Ok(()); } - // TODO: cropping - - let iso_file_size = source_iso_file_meta.len(); - let root_offset = source_iso.volume_descriptor.root_offset; + let data_size = if args.trim { + source_iso.get_max_used_prefix_size() + } else { + let root_offset = source_iso.volume_descriptor.root_offset; + source_iso_file_meta.len() - root_offset + }; - let block_count = div_ceil(iso_file_size - root_offset, god::BLOCK_SIZE as u64); + let block_count = div_ceil(data_size, god::BLOCK_SIZE as u64); let part_count = div_ceil(block_count, god::BLOCKS_PER_PART); // the original code does not seem to support other types @@ -94,7 +102,10 @@ fn main() -> Result<(), Error> { ensure_empty_dir(&file_layout.data_dir_path()).context("error clearing data directory")?; - let mut source_iso = source_iso.get_root().context("error reading source iso")?; + let mut source_iso = source_iso + .get_root() + .context("error reading source iso")? + .take(data_size); println!("writing part files"); diff --git a/src/iso/mod.rs b/src/iso/mod.rs index 201c6c7..9e6ddd8 100644 --- a/src/iso/mod.rs +++ b/src/iso/mod.rs @@ -55,6 +55,23 @@ impl IsoReader { Ok(None) } } + + pub fn get_max_used_prefix_size(&self) -> u64 { + return rec(&self.directory_table); + fn rec(dir: &DirectoryTable) -> u64 { + dir.entries + .iter() + .map(|entry| { + let mut v = (entry.sector as u64) * SECTOR_SIZE + (entry.size as u64); + if let Some(subdir) = &entry.subdirectory { + v = v.max(rec(subdir)); + } + v + }) + .max() + .unwrap_or(0) + } + } } #[derive(Clone, Debug)]