#!/bin/bash

#export PS4="\$LINENO: "
#set -xv

# Some time back I was sent a set of .IMD files which were copies of SIG/M disks from the collection of
# one T Kirk. This BASH script is an attempt to extract the contents of those images. Just place it in
# a directory together with the .IMD images and run it. It will do the following:
#
#     1. Convert the IMD image to the image type specified in $imgtype
#     2. Attempt to extract the files using each of the diskdefs in $fmts
#     3. Compare the extracted files to my SIG/M collection and report the results
#
# The simplest way to use this script is to place it in the same dir with the .IMD files. When run
# without parameters, this script will extract contents from all .IMD it finds using every diskdef
# found in your cpmtools diskdefs file. Or you can specify which .IMD(s) to process, which diskdefs
# definitions to use, etc. Run the script with "-?" to find out more.
# 
# Requirements:
#   - cpmtools (with ImageDisk support)
#   - disk-analyse from ImageDisk
#   - the SIG/M collection from *HUMONGOUS* CP/M, with each volume extracted
#     into subdirs such as sigmv001, etc.

# VERSIONS
# 20230417 - Fleshed out the "Requirements" description.
#
# 20230416 - Added checks for cpmtools, imagedisk and diff.
#          - Spun "Usage:" into its own function.
#          - Tweaked the help screen
#
# 20230415 - Call it v1.0. All major pieces in place. Anticipate only bug fixes, small improvements from here.

  function briefhelp () {
  cat << EOF
  Usage: ./$(basename $0) [-d /path/to/diskdefs/file] [-f 'format1 format2'] [-i 'file1.IMD file2.IMD'] \\
                      [-r /path/to/IMD/files] [-s /path/to/SIGM/files] [-t imagetype] [-?]
EOF
  }
  
  function showhelp () {
  cat << EOF
  -------------------------------------------------------------------------------------------------------------
  This script extracts the contents of the .IMD files in the tkirk collection. The easiest way to run it is to
  simply place it in the same dir with the .IMD files and run './$(basename $0)' without parameters. It requires
  the ImageDisk and cpmtools (with ImageDisk support) utilities be installed.
  
EOF

  briefhelp
  
  cat << EOF

  Options:
    -d /path/to/cpmtools/diskdef               # specify the location and name of your cpmtools diskdefs file
    -f "format1 format2"                       # specify the cpmtools diskdef format(s) to use in extraction
    -i "file1.IMD file2.IMD"                   # list of .IMD files to be processed
    -r /path/to/.IMD/files                     # where the tkirk .IMD files are located
    -s /path/to/SIGM/                          # root dir of your SIG/M collection; expects to find a dir for 
                                               #   each SIGM vol with names like sigmv001/ etc.
    -t  IMG | DSK | RAW                        # specify which disk-analyse disk format to convert IMD to
    -?                                         # display this help screen
    
  Examples:
    ./$(basename $0)                               # Assumes being run from the dir with the .IMD files
    ./$(basename $0) -i "SD241.IMD" -f "ibm-3740"  # Process SD241.IMD using diskdef ibm-3740
    ./$(basename $0) -d ~/cpmtools/diskdefs        # Specify the diskdefs to use
    ./$(basename $0) | tee -a results              # Run with defaults; capture output to "results"
  -------------------------------------------------------------------------------------------------------------
EOF
 }
 
# -------- VARIABLES ----------

      # Get user specified values

      while getopts ':d:f:i:r:s:t:' OPTION; do
        case "$OPTION" in
          d) diskdefs="$OPTARG" ;;                                             # -d /path/to/cpmtools/diskdef
          f)  formats="$OPTARG" ;;                                             # -f "format1 format2"                       # cpmtools disk formats to use
          i) IMDfiles="$OPTARG" ;;                                             # -i "file1.IMD file2.IMD"                   # list of .IMD files to be processed
          r)  imdroot="$OPTARG" ;;                                             # -r /path/to/.IMD/files
          s)     sigm="$OPTARG" ;;                                             # -s /path/to/SIGM/                          # expects to find a dir for each SIGM vol with names like sigmv001/ etc.
          t)  imgtype="$OPTARG" ;;                                             # -t IMG | DSK | RAW                         # specify which of three disk-analyse disk formats to convert IMD to
          ?) showhelp ;  exit 0 ;;
        esac
      done

      # Set defaults
      
      [[ -z "$diskdefs"                  ]] && diskdefs=/usr/local/share/diskdefs  
      [[ -z "$formats"                   ]] && formats=$(grep 'diskdef' $diskdefs | cut -d ' ' -f 2) # default to all formats in diskdefs
      [[ -z "$imdroot"                   ]] && imdroot=$(pwd)                     
      [[ -z "$imgtype"                   ]] && imgtype=IMG                        
      [[ -z "$sigm"                      ]] && for s in "/home/nathanael/mounts/saruman/web/cpmarchives/cpm/Software/UserGroups/SIGM/" "/home/nathanael/host/shared/SIGM"; do [[ -d $s/sigmv001 ]] && sigm=$s; done
      [[ -z "$IMDfiles"                  ]] && IMDfiles=$(ls -a1 $imdroot/*.IMD | rev | cut -d '/' -f 1 | rev)

      # Validate
      
      [[ ! -f $diskdefs                  ]] && { echo "Can't find $diskdefs."                      ; showhelp ; exit 1; }
      [[   -z $IMDfiles                  ]] && { echo "No $imdroot/*.IMD files found."             ; showhelp ; exit 1; }
      [[ ! "IMG DSK RAW" == *"$imgtype"* ]] && { echo "Unknown image type. Using IMG"; imgtype=IMG                    ; }
      [[ ! -d $sigm/sigmv001             ]] && { echo "No recognizable SIG/M files found."         ; showhelp ; exit 1; }
      [[ $(which cpmcp)                  ]] || { echo "cpmtools not found."                        ;            exit 1; }
      [[ $(which disk-analyse)           ]] || { echo "ImageDisk's disk-analyse not found."        ;            exit 1; }
      [[ $(which diff)                   ]] || { echo "'diff' not found."                          ;            exit 1; }

      # Report to user
      
#      printf "%10s : %s\n\n" diskdefs "$diskdefs"
#      printf "%10s : %s\n\n"  formats "$formats"
#      printf "%10s : %s\n\n"  imdroot "$imdroot"
#      printf "%10s : %s\n\n"  imgtype "$imgtype"
#      printf "%10s : %s\n\n"     sigm "$sigm"
#      printf "%10s : %s\n\n" IMDfiles "$IMDfiles"

      briefhelp
      
      echo "                                                                                            "                  
      echo " ------------------------------------------------------------------------------------------ "                  
      echo " A diff is run between the extracted files in the subdirectories with the reference set of  "                  
      echo " SIG/M files at $sigm.                                                                      "                  
      echo "                                                                                            "                  
      echo " 'Not found' : the file was not found in the reference set. Check the \$sigm variable for   "                  
      echo "      the correct location of your SIG/M files, and be sure you're comparing to the correct "                  
      echo "      volume, as specified in variables \$v1 and \$v2.                                      "                  
      echo "                                                                                            "                  
      echo " 'Differs' : the extracted file differs from its reference counterpart. Probably means the  "                  
      echo "      extracted file is corrupt, which means the wrong format was used.                     "                  
      echo "                                                                                            "                  
      echo "  'Matches' : The extracted file matches its reference file counterpart.                    "                  
      echo "                                                                                            "                  
      echo " ------------------------------------------------------------------------------------------ "                  
      echo "                                                                                            "                  
            
  # ---------- MAIN LOOP ----------
  
    for imdfile in $IMDfiles; do                                               # CYCLE THROUGH .IMD FILES
      imdfile=$imdroot/$imdfile                                                # prefix the path
      fmts=$formats                                                            # refresh $fmts in case it was changed below
      imdname=$(echo $imdfile | rev | cut -d '/' -f 1 | rev | cut -d '.' -f 1) # extract only name portion of .IMD file
      imgdir=$imdroot/$imdname                                                 # the dir the .IMD contents will be extracted into   
      imgfile=$imgdir/$imdname.$imgtype                                        # the image file to convert the .IMD to
      case $imdname in                                                         # set some per-IMD variables
         SD239) v1=239 ; v2=239 fmts="ibm-3740"      ;;                        # if the correct format is known, specify it here
         SD240) v1=240 ; v2=240 fmts="ibm-3740"      ;;                        
         SD241) v1=241 ; v2=241                      ;;                        # otherwise leave fmts set to all
             0) v1=001 ; v2=001                      ;;                        
        VOL000) v1=157 ; v2=157                      ;;                        
       VOL000B) v1=023 ; v2=023                      ;;                        
        VOL011) v1=011 ; v2=011 fmts="ibm-3740"      ;;                        
        VOL020) v1=020 ; v2=020 fmts="ibm-3740"      ;;                        
        VOL149) v1=149 ; v2=149 fmts="ibm-3740"      ;;                        
        VOL153) v1=153 ; v2=153 fmts="ibm-3740"      ;;                        
        VOL157) v1=157 ; v2=157 fmts="ibm-3740"      ;;                        
        VOL164) v1=164 ; v2=164 fmts="ibm-3740"      ;;                        
        VOL165) v1=165 ; v2=165 fmts="ibm-3740"      ;;                        
        VOL166) v1=166 ; v2=166 fmts="ibm-3740"      ;;                        
        VOL167) v1=167 ; v2=167 fmts="ibm-3740"      ;;                        
        VOL168) v1=168 ; v2=168 fmts="ibm-3740"      ;;                        
        VOL172) v1=172 ; v2=172 fmts="ibm-3740"      ;;                              
        VOL173) v1=173 ; v2=173 fmts="ibm-3740"      ;;                        
        VOL175) v1=175 ; v2=175 fmts="ibm-3740"      ;;                              
        VOL176) v1=176 ; v2=176 fmts="ibm-3740"      ;;                        
        VOL197) v1=197 ; v2=197 fmts="ibm-3740"      ;;                        
       VOL1881) v1=018 ; v2=081                      ;;                                                      
       VOL2018) v1=018 ; v2=020 fmts="ibm-3740"      ;;                        
       VOL3949) v1=039 ; v2=049                      ;;                                                      
        154F83) v1=154 ; v2=154                      ;;                        
        197207) v1=197 ; v2=207                      ;;                                                      
        210212) v1=210 ; v2=212                      ;;                        
        216217) v1=216 ; v2=217                      ;;                        
        229247) v1=229 ; v2=247                      ;;                        
         SIGM0) v1=157 ; v2=157 fmts="ibm-3740"      ;;                        
      USERSGRO) v1=002 ; v2=002                      ;;                        
          UTIL) v1=089 ; v2=089                      ;;                        
           172) v1=172 ; v2=172 fmts="ibm-3740"      ;;                                    
           194) v1=194 ; v2=194 fmts="ibm-3740"      ;;                        
           197) v1=197 ; v2=197 fmts="ibm-3740"      ;;                                          
           207) v1=207 ; v2=207 fmts="ibm-3740"      ;;                                                            
           210) v1=210 ; v2=210 fmts="ibm-3740"      ;;                        
           211) v1=211 ; v2=211 fmts="ibm-3740"      ;;                                    
           212) v1=212 ; v2=212                      ;;                        
           216) v1=216 ; v2=216                      ;;                        
           217) v1=217 ; v2=217                      ;;                        
           229) v1=229 ; v2=229 fmts="ibm-3740"      ;;                                    
      esac                                                                     

      mkdir -p $imdroot/$imdname; cd $imdroot/$imdname                         
      
      echo " "
      echo " "
      for i in $( seq 1 ${#imdname} ); do printf "="; done; printf "\n"                                                                                                          
      echo $imdname                                                                                                        
      for i in $( seq 1 ${#imdname} ); do printf "="; done; printf "\n"                                                                                                          
      printf "Converting %s to %s\n" $imdfile $imgfile
      disk-analyse $imdfile $imgfile  1> /dev/null 2> /dev/null                # Convert IMD file

      for fmt in $fmts; do                                                     # Cycle through all specified formats
        mkdir -p $imdroot/$imdname/$fmt; cd $imdroot/$imdname/$fmt             # Create a directory for this format attempt
        echo " "                                                               # Report to user
        for i in $( seq 1 ${#fmt} ); do printf "-" ; done ; printf "\n"                                                                                                        
        echo $fmt                                                                                                                                                        
        for i in $( seq 1 ${#fmt} ); do printf "-" ; done ; printf "\n"                                                                                                        

        cpmcp -f $fmt $imgfile 0:*.* ./ 1> /dev/null 2> /dev/null              # Extract the contents using the current format
        
        if [ ! -z "$(ls -A $imdroot/$imdname/$fmt/)" ]; then                   # if the dir is not empty...
          for file in $imdroot/$imdname/$fmt/*; do                             # ...compare each extracted file to the reference volume
            printf "%14s : " $(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_')                                                                                                                                                                                                                
                                      [[ ! -f $sigm/sigmv$v1/$(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_') ]] &&   [[ ! -f         $sigm/sigmv$v2/$(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_')  ]] && printf "Not found"                                     # if file doesn't exist in either reference volume
                                      [[   -f $sigm/sigmv$v1/$(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_') ]] && { [[ $(diff $file $sigm/sigmv$v1/$(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_')) ]] && printf "Differs [$v1] " || printf "Matches [$v1] " ; } # if the file is in the first reference volume, compare
            [[ ! "$v1" == "$v2" ]] && [[   -f $sigm/sigmv$v2/$(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_') ]] && { [[ $(diff $file $sigm/sigmv$v2/$(echo $file | rev | cut -d '/' -f 1 | rev | tr 'a-z' 'A-Z' | tr ',' '_')) ]] && printf "Differs [$v2] " || printf "Matches [$v2] " ; } # if v1 and v2 aren't the same, and the file is in the second reference volume, compare
            printf "\n"                                                                                                                                                                                                                                                                                 
          done  
        else
          printf "  No files\n\n"
        fi

      done # for loop                                                                    
    done                                                                       

# ----------------------------------------------------------
