From 5d3b93844e6f3318b66c144b1148b8329400f2cd Mon Sep 17 00:00:00 2001 From: Ilia Pozdnyakov Date: Mon, 7 Oct 2024 00:49:49 +0500 Subject: [PATCH] clean up code and update wording --- README.md | 4 +-- examples/game_title/main.rs | 26 ++++++++++++-- examples/game_title/unity.rs | 27 ++++++++------- examples/list_files.rs | 2 +- src/bin/iso2god.rs | 2 +- src/executable/mod.rs | 66 ++++++++++++++---------------------- 6 files changed, 68 insertions(+), 59 deletions(-) diff --git a/README.md b/README.md index f942a2d..a44c8df 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # iso2god-rs -A tool to convert Xbox 360 ISOs into a Games-On-Demand file format +A tool to convert Xbox 360 and original Xbox ISOs into an Xbox 360 compatible Games-On-Demand file format This is an optimized rewrite of https://github.com/eliecharra/iso2god-cli, with a few extra features. @@ -7,7 +7,7 @@ This is an optimized rewrite of https://github.com/eliecharra/iso2god-cli, with Usage: iso2god [OPTIONS] Arguments: - Xbox 360 ISO file to convert + ISO file to convert A folder to write resulting GOD files to Options: diff --git a/examples/game_title/main.rs b/examples/game_title/main.rs index 43d06fa..0ccad94 100644 --- a/examples/game_title/main.rs +++ b/examples/game_title/main.rs @@ -19,12 +19,34 @@ struct Cli { source: Source, title_id: String, + + #[arg(long, short = 't', value_enum)] + title_type: Option, +} + +#[derive(Clone, clap::ValueEnum)] +enum CliTitleType { + Xbox360, + Xbla, + OriginalXbox, + Homebrew, +} +impl Into for CliTitleType { + fn into(self) -> unity::TitleType { + match self { + CliTitleType::Xbox360 => unity::TitleType::Xbox360, + CliTitleType::Xbla => unity::TitleType::Xbla, + CliTitleType::OriginalXbox => unity::TitleType::Xbox1, + CliTitleType::Homebrew => unity::TitleType::HomeBrew, + } + } } fn main() -> Result<(), Error> { let args = Cli::parse(); - let title_id = u32::from_str_radix("4D530064", 16)?; + let title_id = u32::from_str_radix(&args.title_id, 16)?; + let title_type = args.title_type.map(|x| x.into()); match args.source { Source::BuiltIn => { @@ -45,7 +67,7 @@ fn main() -> Result<(), Error> { let client = unity::Client::new().context("error creating XboxUnity client")?; let unity_title_info = client - .find_xbox_360_title_id(title_id) + .find_title(title_type, title_id) .context("error querying XboxUnity")?; if let Some(unity_title_info) = &unity_title_info { diff --git a/examples/game_title/unity.rs b/examples/game_title/unity.rs index 1fcdfda..b2fae62 100644 --- a/examples/game_title/unity.rs +++ b/examples/game_title/unity.rs @@ -61,9 +61,6 @@ impl fmt::Display for Title { #[derive(Deserialize, PartialEq, Eq)] pub enum TitleType { - #[serde(rename = "")] - Xbox, - #[serde(rename = "360")] Xbox360, @@ -77,10 +74,9 @@ pub enum TitleType { impl fmt::Display for TitleType { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Xbox => write!(f, "Xbox title"), Self::Xbox360 => write!(f, "Xbox 360 title"), Self::Xbla => write!(f, "Xbox Live Arcade title"), - Self::Xbox1 => write!(f, "Xbox One title"), + Self::Xbox1 => write!(f, "Original Xbox title"), Self::HomeBrew => write!(f, "Homebrew title"), } } @@ -129,21 +125,28 @@ impl Client { Ok(response) } - pub fn find_xbox_360_title_id(&self, title_id: u32) -> Result, Error> { + pub fn find_title( + &self, + title_type: Option, + title_id: u32, + ) -> Result, Error> { let title_id = format!("{:08X}", title_id); let title_list = self.search(&title_id)?; - let best_title = title_list + let mut candidates = title_list .items .into_iter() - .filter(|t| t.title_id == title_id) - .min_by_key(|t| match t.title_type { + .filter(|t| t.title_id == title_id); + + if let Some(title_type) = title_type { + Ok(candidates.find(|t| t.title_type == title_type)) + } else { + Ok(candidates.min_by_key(|t| match t.title_type { TitleType::Xbox360 => 0, TitleType::Xbla => 1, _ => 2, - }); - - Ok(best_title) + })) + } } } diff --git a/examples/list_files.rs b/examples/list_files.rs index dfc73b4..7f89408 100644 --- a/examples/list_files.rs +++ b/examples/list_files.rs @@ -13,7 +13,7 @@ use iso2god::iso; #[command(author, version, about, long_about = None)] #[command(color = clap::ColorChoice::Never)] struct Cli { - /// Xbox 360 ISO file + /// ISO file source_iso: PathBuf, } diff --git a/src/bin/iso2god.rs b/src/bin/iso2god.rs index b195455..4a78882 100644 --- a/src/bin/iso2god.rs +++ b/src/bin/iso2god.rs @@ -18,7 +18,7 @@ use iso2god::{game_list, god, iso}; #[command(author, version, about, long_about = None)] #[command(color = clap::ColorChoice::Never)] struct Cli { - /// Xbox 360 ISO file to convert + /// ISO file to convert source_iso: PathBuf, /// A folder to write resulting GOD files to diff --git a/src/executable/mod.rs b/src/executable/mod.rs index 0b4b123..7cd2e10 100644 --- a/src/executable/mod.rs +++ b/src/executable/mod.rs @@ -1,6 +1,6 @@ use crate::god::ContentType; use crate::iso::IsoReader; -use anyhow::{anyhow, Context, Error}; +use anyhow::{bail, Context, Error}; use byteorder::{ReadBytesExt, BE, LE}; use std::io::{Read, Seek, SeekFrom}; @@ -60,48 +60,32 @@ impl TitleExecutionInfo { impl TitleInfo { pub fn from_image(iso_image: &mut IsoReader) -> Result { - let content_type; - let mut executable; + if let Some(mut executable) = iso_image.get_entry(&"\\default.xex".into())? { + let default_xex_header = + xex::XexHeader::read(&mut executable).context("error reading default.xex")?; + let execution_info = default_xex_header + .fields + .execution_info + .context("no execution info in default.xex header")?; - match iso_image.get_entry(&"\\default.xex".into())? { - Some(entry) => { - executable = entry; - content_type = ContentType::GamesOnDemand; - } - None => { - executable = iso_image - .get_entry(&"\\default.xbe".into())? - .ok_or_else(|| anyhow!("no executable found in this image"))?; - content_type = ContentType::XboxOriginal; - } - } - - let execution_info; - - match content_type { - ContentType::GamesOnDemand => { - let default_xex_header = - xex::XexHeader::read(&mut executable).context("error reading default.xex")?; + Ok(TitleInfo { + content_type: ContentType::GamesOnDemand, + execution_info, + }) + } else if let Some(mut executable) = iso_image.get_entry(&"\\default.xbe".into())? { + let default_xbe_header = + xbe::XbeHeader::read(&mut executable).context("error reading default.xbe")?; + let execution_info = default_xbe_header + .fields + .execution_info + .context("no execution info in default.xbe header")?; - execution_info = default_xex_header - .fields - .execution_info - .context("no execution info in default.xex header")?; - } - ContentType::XboxOriginal => { - let default_xbe_header = - xbe::XbeHeader::read(&mut executable).context("error reading default.xbe")?; - - execution_info = default_xbe_header - .fields - .execution_info - .context("no execution info in default.xbe header")?; - } + Ok(TitleInfo { + content_type: ContentType::XboxOriginal, + execution_info, + }) + } else { + bail!("no executable found in this image"); } - - Ok(TitleInfo { - content_type, - execution_info, - }) } }