Skip to content

Commit

Permalink
clean up code and update wording
Browse files Browse the repository at this point in the history
  • Loading branch information
iliazeus committed Oct 8, 2024
1 parent 44d8138 commit 5d3b938
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 59 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
# 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.

```
Usage: iso2god [OPTIONS] <SOURCE_ISO> <DEST_DIR>
Arguments:
<SOURCE_ISO> Xbox 360 ISO file to convert
<SOURCE_ISO> ISO file to convert
<DEST_DIR> A folder to write resulting GOD files to
Options:
Expand Down
26 changes: 24 additions & 2 deletions examples/game_title/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,34 @@ struct Cli {
source: Source,

title_id: String,

#[arg(long, short = 't', value_enum)]
title_type: Option<CliTitleType>,
}

#[derive(Clone, clap::ValueEnum)]
enum CliTitleType {
Xbox360,
Xbla,
OriginalXbox,
Homebrew,
}
impl Into<unity::TitleType> 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 => {
Expand All @@ -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 {
Expand Down
27 changes: 15 additions & 12 deletions examples/game_title/unity.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,6 @@ impl fmt::Display for Title {

#[derive(Deserialize, PartialEq, Eq)]
pub enum TitleType {
#[serde(rename = "")]
Xbox,

#[serde(rename = "360")]
Xbox360,

Expand All @@ -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"),
}
}
Expand Down Expand Up @@ -129,21 +125,28 @@ impl Client {
Ok(response)
}

pub fn find_xbox_360_title_id(&self, title_id: u32) -> Result<Option<Title>, Error> {
pub fn find_title(
&self,
title_type: Option<TitleType>,
title_id: u32,
) -> Result<Option<Title>, 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)
}))
}
}
}
2 changes: 1 addition & 1 deletion examples/list_files.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}

Expand Down
2 changes: 1 addition & 1 deletion src/bin/iso2god.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
66 changes: 25 additions & 41 deletions src/executable/mod.rs
Original file line number Diff line number Diff line change
@@ -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};

Expand Down Expand Up @@ -60,48 +60,32 @@ impl TitleExecutionInfo {

impl TitleInfo {
pub fn from_image<R: Read + Seek>(iso_image: &mut IsoReader<R>) -> Result<TitleInfo, Error> {
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,
})
}
}

0 comments on commit 5d3b938

Please sign in to comment.