iso2god

repository·master·Indexed 42 days ago

https://github.com/iliazeus/iso2god-rs

A high-performance tool to convert Xbox 360 and original Xbox ISO images into the Games-On-Demand (GOD) file format. Version 1.8.0 features metadata extraction, parallel processing for faster conversion, and ISO trimming to reduce file size.

Tokens
6.5K
Snippets
29
Records
37
Agent score
55%

What's inside iso2god

  1. Convert Xbox ISOs to Games-On-Demand format with iso2god

    master

    Use iso2god to convert Xbox 360 and original Xbox ISO files into the Xbox 360 compatible Games-On-Demand (GOD) file format. This tool is an optimized rewrite of iso2god-cli.

    iso2god [OPTIONS] <SOURCE_ISO> <DEST_DIR>
  2. Use the iso2god CLI to convert ISO files

    master

    The iso2god command-line tool converts ISO images into GOD (Games on Demand) format. It extracts metadata from the source ISO, determines the content type (Games on Demand or Xbox Original), and writes the resulting part files and .con header to a destination directory.

    Basic Usage:

    iso2god <source_iso> <dest_dir>

    Key Features:

    • Metadata Extraction: Automatically identifies Title ID, Game Name, and Content Type.
    • Trimming: Can trim unused space from the end of the ISO to reduce the size of the resulting GOD files.
    • Parallel Processing: Uses multiple threads to speed up the writing of part files.
    • Dry Run: Allows you to inspect the ISO metadata without performing any conversion.
    iso2god my_game.iso ./output_folder
  3. Optimize performance with threads

    master

    By default, iso2god uses 1 thread. On non-Windows systems or when using SSDs, you can significantly increase performance by specifying a higher number of threads using the -j or --num-threads flag.

    Warning: On Windows or when using traditional hard drives, the default is set to 1 thread to avoid potential issues with file access and drive performance.

    iso2god source.iso ./dest -j 8
  4. Configure ISO trimming modes

    master

    The --trim flag controls how unused space is handled during conversion. This affects the final size of the generated GOD files.

    Available Modes:

    • from-end (default): Trims unallocated space from the end of the ISO image.
    • none: Trims nothing; the size is calculated based on the volume descriptor's root offset.

    Note: Passing no --trim flag at all is equivalent to using from-end.

    iso2god source.iso ./dest --trim none
  5. Use iso2god CLI arguments and options

    master

    The iso2god CLI tool accepts a source ISO file and a destination directory as positional arguments. You can use several options to customize the conversion process.

    Arguments:
      <SOURCE_ISO>  ISO file to convert
      <DEST_DIR>    A folder to write resulting GOD files to
    
    Options:
          --dry-run             Do not convert anything, just print the title info
          --game-title <TITLE>  Set game title
          --trim                Trim off unused space from the ISO image
      -j, --num-threads <N>     Number of worker threads to use
      -h, --help                Print help
      -V, --version             Print version
  6. Parse XEX headers with XexHeader::read

    master

    To parse an Xbox 360 executable (XEX) header, use the XexHeader::read method. This method requires a reader that implements both std::io::Read and std::io::Seek. It validates the magic bytes (expecting XEX2) and extracts module flags, code offsets, certificate offsets, and various header fields.

    If the header is invalid or missing the XEX2 magic bytes, it will return an error: missing 'XEX2' magic bytes in XEX header.

    use crate::executable::xex::XexHeader;
    use std::fs::File;
    
    let mut file = File::open("path/to/executable.xex")?;
    let header = XexHeader::read(&mut file)?;
    
    println!("Module Flags: {:?}", header.module_flags);
    println!("Code Offset: {}", header.code_offset);
  7. Get the digest or raw bytes of a HashList

    master

    To retrieve data from a HashList:

    • digest(&self) -> [u8; 20]: Returns a single 20-byte SHA-1 digest of the entire internal buffer.
    • bytes(&self) -> &[u8; 4096]: Returns a reference to the raw 4096-byte internal buffer.
    • write<W: Write>(&self, mut writer: W): Writes the entire 4096-byte buffer to the provided writer.
  8. Retrieve a file or directory entry by path

    master

    Use get_entry(path: &WindowsPath) to locate a specific file or directory within the ISO.

    • Path Format: Use WindowsPath which uses backslashes (\) as separators.
    • Return Value: Returns Ok(Some(&mut R)) where the reader is positioned at the start of the requested entry's data, or Ok(None) if the path does not exist.
    • Behavior: The method traverses the DirectoryTable hierarchy based on the provided path components.
    use iso::WindowsPath;
    
    // Access a file at 'folder\file.txt'
    let path = WindowsPath::from("folder\\file.txt");
    if let Some(entry_reader) = iso_reader.get_entry(&path)? {
        // entry_reader is now positioned at the start of the file data
    }
  9. Write GOD file parts with write_part

    master

    The write_part function is used to extract and write a specific part of a data volume into a GOD file format. It handles the calculation of offsets, the generation of subpart hash lists, and the construction of the master hash list for the part.

    Constants used for GOD file structure:

    • BLOCK_SIZE: 0x1000 bytes
    • BLOCKS_PER_SUBPART: 0xcc blocks
    • SUBPARTS_PER_PART: 0xcb subparts
    • SUBPART_SIZE: BLOCK_SIZE * BLOCKS_PER_SUBPART
    • BLOCKS_PER_PART: 0xa1c4 blocks

    Function Signature:

    pub fn write_part<R: Read + Seek, W: Write + Seek>(mut data_volume: R, part_index: u64, mut part_file: W) -> Result<(), Error>

    • data_volume: A reader that implements Read and Seek, representing the source data.
    • part_index: The index of the part to be written.
    • part_file: A writer that implements Write and Seek, representing the destination GOD part file.

    Behavior:

    1. Seeks to the correct position in the data_volume based on the part_index.
    2. Iterates through subparts within the part.
    3. For each subpart, it calculates a HashList of the block hashes.
    4. Writes the subpart data and its hash list to the part_file.
    5. Finally, it writes the master_hash_list at the beginning of the part file to maintain the GOD structure.
    // Example usage (requires implementing Read/Seek/Write for your types)
    write_part(data_volume, part_index, part_file)?;
  10. Calculate the minimum required ISO size

    master

    Use get_max_used_prefix_size() to determine the minimum number of bytes required to represent the entire ISO structure. This calculation accounts for:

    • The volume descriptor extent.
    • The root directory table extent.
    • The extents of all files and subdirectories within the DirectoryTable hierarchy.

    This is useful for trimming images or determining how much data must be read to ensure a complete capture of the filesystem structure.

    let min_size = iso_reader.get_max_used_prefix_size();
  11. Access the ISO root directory

    master

    Use get_root() to seek the underlying reader to the start of the root directory table. This returns a mutable reference to the reader R, allowing you to read the raw bytes of the root directory.

    let mut iso_reader = IsoReader::read(file)?;
    let root_reader = iso_reader.get_root()?;
    // Use root_reader to read directory data
  12. Extract TitleInfo from an ISO image

    master

    The TitleInfo::from_image method is the primary way to identify the content and execution metadata of an ISO image. It automatically detects the executable type by searching for specific files in the image root:

    1. XEX (Games on Demand): If \default.xex is found, it returns ContentType::GamesOnDemand and extracts the execution_info from the XEX header.
    2. XBE (Xbox Original): If \default.xbe is found, it returns ContentType::XboxOriginal and extracts the execution_info from the XBE header.

    If neither file is found, it returns an error: "no executable found in this image".

    use crate::executable::TitleInfo;
    use crate::iso::IsoReader;
    use std::fs::File;
    
    let mut iso_file = File::open("image.iso")?;
    let mut iso_reader = IsoReader::new(&mut iso_file);
    let title_info = TitleInfo::from_image(&mut iso_reader)?;
    
    println!("Content Type: {:?}", title_info.content_type);
    println!("Title ID: {}", title_info.execution_info.title_id);