#!/bin/bash # --- Theme Configuration (Orange & Grey) --- ORANGE="#FF6B00" GREY_LIGHT="#B3B3B3" GREY_DARK="#2E2E2E" export GUM_CHOOSE_CURSOR_FOREGROUND="$ORANGE" export GUM_CHOOSE_SELECTED_FOREGROUND="$ORANGE" export GUM_CHOOSE_ITEM_FOREGROUND="$GREY_LIGHT" export GUM_CONFIRM_SELECTED_BACKGROUND="$ORANGE" export GUM_CONFIRM_SELECTED_FOREGROUND="#000000" export GUM_CONFIRM_UNSELECTED_BACKGROUND="$GREY_DARK" export GUM_CONFIRM_UNSELECTED_FOREGROUND="$GREY_LIGHT" # Create a clean temporary log to trap underlying command errors ERROR_LOG=$(mktemp /tmp/chd_converter_err.XXXXXX) trap 'rm -f "$ERROR_LOG"' EXIT while true; do clear # Title Box Header gum style \ --border double \ --border-foreground "$ORANGE" \ --foreground "$ORANGE" \ --margin "1 2" \ --padding "1 4" \ --align center \ --width 40 \ "CHD ROM Converter" # Main Menu Selection CHOICE=$(gum choose --header="Select an action:" "Compress to CHD" "Extract CHD back to ROM" "Exit") case "$CHOICE" in "Compress to CHD") gum style --foreground "$ORANGE" "Select the folder containing ROMs to compress:" TARGET_DIR=$(gum file --directory) [ -z "$TARGET_DIR" ] && continue cd "$TARGET_DIR" || continue shopt -s nullglob nocaseglob FILES=(*.iso *.cue *.gdi) if [ ${#FILES[@]} -eq 0 ]; then gum style --foreground "$GREY_LIGHT" "No compatible files (.iso, .cue, .gdi) found in this folder." gum input --placeholder "Press Enter to return to menu..." --timeout 5s >/dev/null continue fi CONVERTED_ORIGINALS=() FAILED_FILES=() for FILE in "${FILES[@]}"; do [ -f "$FILE" ] || continue OUTPUT_CHD="${FILE%.*}.chd" # Wrapped inside bash -c so 'gum spin' output stays visible on the terminal screen gum spin --spinner dot --spinner.foreground "$ORANGE" --title.foreground "$GREY_LIGHT" --title "Compressing: $FILE..." -- bash -c "chdman createcd -i '$FILE' -o '$OUTPUT_CHD' >/dev/null 2>'$ERROR_LOG'" if [ $? -eq 0 ]; then CONVERTED_ORIGINALS+=("$FILE") # Track associated .bin files from inside the .cue file for safe cleanup if [[ "$FILE" =~ \.cue$ ]]; then while IFS= read -r BIN_FILE; do BIN_FILE=$(echo "$BIN_FILE" | tr -d '\r"' | xargs) if [ -f "$BIN_FILE" ]; then CONVERTED_ORIGINALS+=("$BIN_FILE") fi done < <(grep -i 'FILE' "$FILE" | awk -F '"' '{print $2}') fi else FAILED_FILES+=("$FILE") echo "" if grep -qE "not found|command not found" "$ERROR_LOG" 2>/dev/null; then gum style --foreground "#FF3333" --border normal --border-foreground "#FF3333" --padding "0 1" "Error: 'chdman' is not installed or not in your PATH." gum input --placeholder "Press Enter to return to menu..." >/dev/null break 2 fi gum style --foreground "#FF3333" "Failed to compress: $FILE" gum style --foreground "$GREY_LIGHT" "Reason: $(cat "$ERROR_LOG")" echo "" fi done if [ ${#CONVERTED_ORIGINALS[@]} -gt 0 ]; then if gum confirm "Compression complete! Do you want to delete the original source files?"; then for ORIG in "${CONVERTED_ORIGINALS[@]}"; do rm -f "$ORIG" done gum style --foreground "$ORANGE" "Original files cleaned up successfully." sleep 2 fi elif [ ${#FAILED_FILES[@]} -gt 0 ]; then gum style --foreground "$GREY_LIGHT" "File processing halted due to errors shown above." gum input --placeholder "Press Enter to return to menu..." >/dev/null fi ;; "Extract CHD back to ROM") gum style --foreground "$ORANGE" "Select the folder containing CHDs to extract:" TARGET_DIR=$(gum file --directory) [ -z "$TARGET_DIR" ] && continue cd "$TARGET_DIR" || continue shopt -s nullglob nocaseglob FILES=(*.chd) if [ ${#FILES[@]} -eq 0 ]; then gum style --foreground "$GREY_LIGHT" "No .chd files found in this folder." gum input --placeholder "Press Enter to return to menu..." --timeout 5s >/dev/null continue fi CONVERTED_CHDS=() for FILE in "${FILES[@]}"; do [ -f "$FILE" ] || continue BASE_NAME="${FILE%.*}" # Check metadata to safely differentiate between multi-track CD structures and flat DVDs if chdman info -i "$FILE" 2>/dev/null | grep -qi "track"; then # CD Mode (.cue + .bin output alignment) OUTPUT_FILE="$BASE_NAME.cue" gum spin --spinner dot --spinner.foreground "$ORANGE" --title.foreground "$GREY_LIGHT" --title "Extracting CD ROM Layout ($BASE_NAME.cue)..." -- bash -c "chdman extractcd -i '$FILE' -o '$OUTPUT_FILE' >/dev/null 2>'$ERROR_LOG'" else # DVD Mode (True standalone single .iso target extraction) OUTPUT_FILE="$BASE_NAME.iso" gum spin --spinner dot --spinner.foreground "$ORANGE" --title.foreground "$GREY_LIGHT" --title "Extracting DVD Image ($BASE_NAME.iso)..." -- bash -c "chdman extractdvd -i '$FILE' -o '$OUTPUT_FILE' >/dev/null 2>'$ERROR_LOG'" fi if [ $? -eq 0 ]; then CONVERTED_CHDS+=("$FILE") else echo "" if grep -qE "not found|command not found" "$ERROR_LOG" 2>/dev/null; then gum style --foreground "#FF3333" "Error: 'chdman' command not found." gum input --placeholder "Press Enter to return to menu..." >/dev/null break 2 fi gum style --foreground "#FF3333" "Failed to extract: $FILE" gum style --foreground "$GREY_LIGHT" "Reason: $(cat "$ERROR_LOG")" echo "" fi done if [ ${#CONVERTED_CHDS[@]} -gt 0 ]; then if gum confirm "Extraction complete! Do you want to delete the original CHD files?"; then for CHD in "${CONVERTED_CHDS[@]}"; do rm -f "$CHD" done gum style --foreground "$ORANGE" "Original CHD files cleaned up successfully." sleep 2 fi else gum style --foreground "$GREY_LIGHT" "Extraction failed or was aborted." gum input --placeholder "Press Enter to return to menu..." >/dev/null fi ;; "Exit") clear exit 0 ;; esac done