diff --git a/.bashrc b/.bashrc index fda58b1..9abc409 100644 --- a/.bashrc +++ b/.bashrc @@ -64,6 +64,7 @@ function helpme() { echo -e "wii : Convert Wii games" echo -e "nds-patcher : Patches NDS ROMs" echo -e "megadrive : Flashes Megadrive Carts" + echo -e "chd : Converts roms with CHDMAN" echo -e "" echo -e "\e[32m------------ System -------------\e[0m" echo -e "kill [tab] : Show processes to Kill" @@ -105,6 +106,7 @@ alias compress="~/.bash/scripts/compress.sh" alias wii="~/.bash/scripts/wii.sh" alias nds-patcher="~/.bash/scripts/nds.sh" alias megadrive="~/.bash/scripts/megadrive.sh" +alias chd="~/.bash/scripts/chd.sh" alias caddy="~/.bash/scripts/caddy.sh" export GSK_RENDERER=cairo diff --git a/scripts/chd.sh b/scripts/chd.sh new file mode 100755 index 0000000..c58d30c --- /dev/null +++ b/scripts/chd.sh @@ -0,0 +1,173 @@ +#!/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 \ No newline at end of file