Skip to content

MrBlank/image2chd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 

Repository files navigation

image2chd

A Bash script that batch-converts disc images to .chd using chdman, then auto-generates .m3u playlists for multi-disc games.

Supported formats

Input Systems
.cue + .bin PS1, Saturn, PC Engine CD, and most CD-based consoles
.gdi + tracks Dreamcast
.iso (≤ 900 MB) treated as CD
.iso (> 900 MB) PS2, Xbox, GameCube, PSP (UMD) — treated as DVD
.toc, .nrg CD-based

Requirements

chdman (part of MAME tools):

# macOS
brew install rom-tools

# Debian / Ubuntu
sudo apt install mame-tools

# Arch
sudo pacman -S mame-tools

# Fedora
sudo dnf install mame-tools

Usage

image2chd.sh [options] [folder]

folder defaults to the current directory.

Options

Flag Default Description
-m, --mode MODE auto Force conversion mode: auto, cd, or dvd
-t, --threshold-mb N 900 ISO size in MB that separates CD from DVD auto-detection
-b, --backup-dir NAME backup Name of the subfolder originals are moved into
-B, --no-backup Leave originals in place after conversion
-D, --delete-originals Delete originals instead of moving them
-j, --jobs N 1 Convert N games in parallel
-p, --threads N chdman default chdman internal compression threads (-np)
-c, --compression CODEC zlib Compression codec set: zlib (best emulator compatibility), default (chdman's smallest), or any literal codec list (e.g. cdlz,cdzl,cdfl)
-f, --force Overwrite existing .chd files
-n, --dry-run Show what would happen without touching any files
-r, --recursive Walk subfolders to any depth
--top-only Only process files in the root folder; ignore all subfolders
--verify Run chdman verify on each newly created .chd
--no-m3u Skip .m3u playlist generation
--no-progress Hide the progress bar (auto-disabled in parallel mode or non-TTY)
--no-prune Don't remove empty subfolders left behind after cleanup
-h, --help Show help

Examples

Convert everything in the current directory (originals moved to ./backup/):

./image2chd.sh

Convert a specific folder, keep originals, skip playlists:

./image2chd.sh -B --no-m3u ~/roms/ps1

Parallel conversion with 4 jobs, delete originals after success:

./image2chd.sh -j 4 -D ~/roms/ps2

Dry run to preview what would be converted:

./image2chd.sh -n ~/roms/saturn

Force-overwrite existing .chd files and verify each one:

./image2chd.sh -f --verify ~/roms/dreamcast

Use chdman's smaller default codecs instead of zlib (modern emulators only):

./image2chd.sh --compression default ~/roms/ps1

Compression and emulator compatibility

The script defaults to zlib compression (-c cdzl for CD images, -c zlib for DVD images) because it's compatible with virtually every emulator that supports CHD — including older or stripped-down forks like AetherSX2 / NetherSX2 on Android, the original PCSX2, and many retro handhelds. The trade-off is roughly 10–20% larger files than chdman's default.

If you only target modern emulators on PC (latest PCSX2, RetroArch, Duckstation, etc.) and want the smallest files, pass --compression default to let chdman pick its own codecs (typically LZMA-based). For full control, pass any literal codec list, e.g. --compression cdlz,cdzl,cdfl.

Codec preset Used for File size Compatibility
zlib (default) -c cdzl (CD), -c zlib (DVD) Larger Excellent — works everywhere
default no -c flag Smallest Modern emulators only
literal string passed through verbatim Varies You're on your own

How it works

  1. Discovery — finds all .cue, .gdi, .iso, .toc, and .nrg files in the target folder. Default traversal covers the root folder plus one subfolder level deep. Use -r for unlimited depth or --top-only to restrict to the root only. If a .cue or .gdi shares a basename with a .iso, the .iso is skipped to avoid duplicate conversions.
  2. Mode detection — for each file, determines whether to call chdman createcd or chdman createdvd. .cue/.gdi/.toc/.nrg always use CD mode; .iso files are classified by file size against the threshold.
  3. Conversion — runs chdman and writes to a .partial temp file, renaming it only on success. All .chd files are written to the root target folder regardless of where the source was found. Failed conversions leave source files untouched.
  4. Source handling — on success, source files in the root folder are moved to the backup subfolder or deleted immediately. Sources found in subfolders are handled as a unit: the entire subfolder is moved or deleted only after every input inside it has been successfully converted. If any conversion in a subfolder failed, the subfolder is left in place.
  5. Empty folder pruning — after cleanup, any subfolders left empty (containing only .DS_Store at most) are automatically removed. Disable with --no-prune.
  6. Playlist generation — scans the output folder for files matching Name (Disc N).chd and writes a sorted Name.m3u for any group of two or more discs. Existing .m3u files are never overwritten.

Multi-disc playlists

Playlists are generated automatically. A game like:

Final Fantasy VII (Disc 1).chd
Final Fantasy VII (Disc 2).chd
Final Fantasy VII (Disc 3).chd

produces Final Fantasy VII.m3u containing the three filenames in disc order. Use --no-m3u to disable this.

Notes

  • The script is compatible with bash 3.2+ (the version shipped with macOS).
  • Progress bar is shown only in single-job mode on an interactive terminal. It auto-disables when running in parallel or when stdout is redirected.
  • --no-backup and --delete-originals are mutually exclusive.
  • --recursive and --top-only are mutually exclusive.
  • Exit code is non-zero if any conversion failed (sequential mode only; parallel mode always exits 0).

About

Compress disc images to lossless Compressed Hunks of Data (CHD)

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages