Skip to content

Latest commit

ย 

History

241 Commits

Folders and files

NameName
Last commit message
Last commit date
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

๐ŸŽฎ chdtool

License Release ShellCheck

A robust Bash script for converting CD/DVD disc images and archives into CHD (Compressed Hunks of Data) format using chdman.

Designed for batch processing, validation, logging, and multi-disc handling โ€” ideal for emulation libraries.


Convert everything in a directory:

./chdtool.sh -r /path/to/roms

โœจ Features

  • ๐Ÿ“ฆ Supports common input formats:
    • Archives: zip, rar, 7z
    • Disc images: iso, cue, gdi, ccd
  • ๐Ÿ”„ Automatic extraction of archives before conversion
  • ๐Ÿ’ฟ Intelligent CD vs DVD detection (createcd vs createdvd)
  • โœ… Verification of CHDs using chdman verify
    • Automatic retry on failure
    • Deletes invalid CHDs
  • ๐Ÿ“‰ Space savings reporting
  • ๐Ÿงพ Automatic M3U generation for multi-disc sets
  • ๐Ÿงน Safe temp directory handling with cleanup traps
  • ๐Ÿงช Dry-run mode (no source or conversion changes)
  • ๐Ÿชต Structured logging system:
    • Console / file / syslog / journald
    • Configurable verbosity
  • โšก Progress bar (TTY-aware, non-spammy)

๐Ÿš€ Usage

./chdtool.sh [options] <input directory>

Options

Option Description
-k, --keep-originals Do not delete source files after conversion
-r, --recursive Process subdirectories
-n, --dry-run Show what would happen without making changes
-a, --allow-unverified-cue-audio Permit lossy or unverified CUE audio tracks (not preservation-safe)
-F, --file-tee Force logging to file
-N, --no-file-tee Disable logging to file
-h, --help Show usage information
-V, --version Show the packaged version

Use -- to end option parsing when an input directory starts with -:

./chdtool.sh -- -roms

๐Ÿ“ Example

./chdtool.sh -r /mnt/roms

Dry run:

./chdtool.sh -n /mnt/roms

๐Ÿ“ฆ Supported Input Formats

Disc images

  • .iso
  • .cue (with referenced BIN/WAV/MP3 validation)
  • .gdi
  • .ccd

Archives

  • .zip
  • .rar
  • .7z

Archives are extracted to a temporary directory and processed automatically.


๐Ÿ’ฟ Output

  • CHDs are created alongside the input files
  • Temporary files use .tmp suffix until verified
  • Originals are removed unless --keep-originals is set

๐Ÿงพ Multi-disc Support

  • Automatically detects disc numbering patterns:
    • Disc 1, CD2, Part 3, Side A, 1 of 2, etc.
  • Generates .m3u playlists when 2+ discs are detected
  • Filenames are sanitized for cross-platform compatibility

Example:

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

๐Ÿ” Verification

  • All CHDs are verified with chdman verify
  • Failed verification:
    • Retried once
    • Deleted if still invalid
  • Existing CHDs are verified before skipping conversion

๐Ÿชต Logging

Configurable via environment variables:

LOG_DEST=auto|console|file|syslog|journald
LOG_LEVEL_THRESHOLD=DEBUG|INFO|WARN|ERROR
LOG_TEE_CONSOLE=auto|1|0
LOG_TEE_FILE=1|0
LOG_TAG=chdtool
LOGFILE=/custom/path/chdtool.log

Default log file:

logs/chd_conversion_<timestamp>.log

--file-tee and --no-file-tee control the optional file mirror for console, syslog, and journald backends. When LOG_DEST=file, the file is the primary destination and is therefore still written. A caller-supplied LOGFILE path is used verbatim.


๐Ÿ“Š Output Summary

At the end of a run:

  • Total original size
  • Total CHD size
  • Space saved
  • Archives processed
  • CHDs created
  • Failures
  • Elapsed time

Exit statuses

  • 0 โ€” clean success, including intentional skips and already-complete inputs
  • 1 โ€” usage, configuration, or startup failure
  • 2 โ€” one or more discovered inputs failed; independent inputs were still processed
  • 130 โ€” interrupted by SIGINT or SIGTERM

โš™๏ธ Requirements

The following tools must be installed:

  • chdman
  • unzip
  • unrar
  • 7z
  • stat
  • awk
  • stdbuf

Optional (enhancements):

  • file (better ISO detection)
  • perl (improved filename parsing)
  • uconv (Unicode normalization)
  • systemd-cat / logger (logging backends)

๐Ÿงช Dry Run Mode

Use --dry-run to preview actions:

./chdtool.sh -n /roms
  • No source files, CHDs, playlists, or temporary conversion workspaces are created, moved, or deleted
  • All intended operations are logged

Logging remains active during a dry run and may create the configured log file. Use --no-file-tee with the console, syslog, or journald backend to prevent a file mirror.

Resource selection

By default, CHD Tool lets chdman choose its format-appropriate hunk size. It selects compression threads conservatively from Linux MemAvailable (never swap), using roughly 2 GiB per CD thread or 4 GiB per DVD thread, and caps the result at the available CPU count with a minimum of one.

  • CHDMAN_THREADS=N requests a positive thread count; values above the CPU count are capped
  • CHDMAN_HUNK_SIZE=N is an advanced opt-in that passes -hs N to chdman

โš ๏ธ Notes

  • DVD support requires a version of chdman with createdvd
  • CUE files referencing missing files will fail validation
  • CUE/GDI/CCD paths must be relative and remain below the descriptor directory; nested paths and unambiguous case-insensitive matches are supported
  • A successfully converted direct descriptor is treated as one source set: unless --keep-originals is used, the descriptor and all validated companion tracks are removed together. Any validation or conversion failure retains the full set
  • Archive members are rejected before conversion when paths escape the extraction directory, links are present, or selected entries collide after name sanitisation
  • Temporary files are cleaned automatically, even on interruption
  • --allow-unverified-cue-audio relaxes preservation checks for lossy or otherwise unverified CUE audio tracks; use it only when accepting that risk

๐Ÿ“ฆ Release assets

Each release publishes .tar.gz and .zip archives containing chdtool, README.md, LICENSE, and CHANGELOG.md, plus a standalone chdtool script. Verify downloads with the published checksum file:

sha256sum --check SHA256SUMS

Maintainers should use the documented release procedure rather than creating tags or assets manually.


๐Ÿ› ๏ธ Design Goals

  • Safe by default (verify before replace)
  • Idempotent (re-runs donโ€™t duplicate work)
  • Transparent logging
  • Minimal dependencies
  • Works well on large ROM collections

๐Ÿ“Œ Future Ideas

  • Parallel processing
  • Better metadata integration
  • Optional compression tuning
  • Integration with tools like Retromount / ROM managers

License

This project is licensed under the GNU General Public License v3.0 only.

About

A Bash script that converts CD/DVD disc images (ZIP/RAR/7Z/ISO/CUE/GDI/CCD) into CHD using chdman.

Resources

Code of conduct

Contributing

Security policy

Stars

2 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages