#!/bin/bash # Set variables INFO_MAP_FILENAME="Info_Map.imp" VERBOSE=0 GENERATEXML=0 MAP_FOLDER="" ARCHIVE_FILE="" DIRECT_FILE="" LOG_FILE="./script.log" DEFAULT="" DEPENDENCIES=("7z" "hexdump" "awk") # Functions declaration # Check if all required commands are available check_dependencies() { for cmd in "${DEPENDENCIES[@]}"; do if ! command -v "$cmd" &> /dev/null; then echo "ERROR: Required command '$cmd' is not installed. Please install it and try again." exit 1 fi done } # Log message to console and file log_message() { if [[ $VERBOSE -eq 1 ]]; then echo "$1" | tee -a "$LOG_FILE" else echo "$1" >> "$LOG_FILE" fi } # Clean up temporary files when script exits cleanup() { if [[ -f "/tmp/$INFO_MAP_FILENAME" ]]; then rm "/tmp/$INFO_MAP_FILENAME" fi log_message "Cleaned up temporary files." } trap cleanup EXIT # Progress bar for long operations show_progress() { for i in {1..4}; do sleep 1 case $i in 1) echo -ne 'Processing: [# ] (0%)\r' ;; 2) echo -ne 'Processing: [##### ] (25%)\r' ;; 3) echo -ne 'Processing: [########## ] (50%)\r' ;; 4) echo -ne 'Processing: [############### ] (75%)\r' ;; esac done echo -ne 'Processing: [####################### ] (100%)\r\n' } # Parse Info_Map.imp file parseInfoMapFile() { log_message "Parsing file..." MAP_NAME=$(hexdump -C "$INFOMAP_FILE" | awk -F"|" '{ print $2 }' | tr -d "\n" | cut -c 21-200) MAP_SWID_FscShort=$(hexdump -C "$INFOMAP_FILE" | awk 'NR==1 {print toupper($10$11$12$13)}') MAP_REGION=$(hexdump -C "$INFOMAP_FILE" | awk 'NR==1 {print "0x" toupper($11)}') MAP_YEAR=$(hexdump -C "$INFOMAP_FILE" | awk 'NR==1 {print "0x" toupper($13)}') log_message "Parsing completed [OK]" } # Display map information showMapInfos() { echo -e "\n===================== Map Information =========================" echo -e "Map Name : \"$MAP_NAME\"" echo -e "SWID_FscShort : \"$MAP_SWID_FscShort\"" echo -e "Map Region : \"$MAP_REGION\"" echo -e "Map Year : \"$MAP_YEAR\"" echo -e "===============================================================\n" } # Show the XML entry to add showLookupXMLEntry() { LONG_MAP_NAME="$MAP_NAME (SWID_FscShort=$MAP_SWID_FscShort, MapRegion=$MAP_REGION, MapYear=$MAP_YEAR)" echo -e "\n===================== XML Generation ===========================" echo -e "Add this entry at the end of the maps list in your Lookup.xml file:\n" echo -e "\n\t\n\t\n" echo -e "\n===============================================================\n" } # Validate input file permissions validate_file() { if [[ ! -r "$1" ]]; then echo "ERROR: Cannot read file $1. Check permissions." exit 2 fi } # Process an archive file processArchiveFile() { if [[ ! -f "$ARCHIVE_FILE" ]]; then log_message "ERROR: Archive file \"$ARCHIVE_FILE\" does not exist" exit 2 fi log_message "File archive exists" PATH_TO_INFOMAP_FILE=$(7z l "$ARCHIVE_FILE" | grep "$INFO_MAP_FILENAME" | grep -v "LIGHT" | awk '{print $NF}') log_message "Looking for \"$INFO_MAP_FILENAME\" in the archive... [OK] - $PATH_TO_INFOMAP_FILE" filename=$(basename -- "$ARCHIVE_FILE") extension="${filename##*.}" case "$extension" in "7z"|"7Z") log_message "Extracting \"$INFO_MAP_FILENAME\" from 7zip archive..." show_progress 7z -y e "$ARCHIVE_FILE" -o"/tmp" "$PATH_TO_INFOMAP_FILE" ;; "zip"|"ZIP"|"tar") show_progress 7z -y e "$ARCHIVE_FILE" -o"/tmp" "$PATH_TO_INFOMAP_FILE" > /dev/null ;; *) log_message "Unsupported archive format: $extension" exit 2 ;; esac if [[ -f "/tmp/$INFO_MAP_FILENAME" ]]; then INFOMAP_FILE="/tmp/$INFO_MAP_FILENAME" else log_message "ERROR: \"$INFO_MAP_FILENAME\" not found in /tmp" exit 2 fi } # Process map folder processFolder() { log_message "Processing folder \"$MAP_FOLDER\"..." if [[ -d "$MAP_FOLDER/1" ]]; then INFOMAP_FILE=$(find "$MAP_FOLDER/1" -name "$INFO_MAP_FILENAME" | grep -v "LIGHT" | head -n 1) if [[ -z "$INFOMAP_FILE" ]]; then log_message "ERROR: \"$INFO_MAP_FILENAME\" not found in folder(s) 1/INFO*" exit 2 fi else log_message "ERROR: Folder \"$MAP_FOLDER\" does not contain expected map files" exit 2 fi } # Batch process for multiple maps process_batch() { for file in "$1"/*; do if [[ -d "$file" ]]; then log_message "Processing folder: $file" processFolder "$file" elif [[ -f "$file" ]]; then log_message "Processing archive: $file" processArchiveFile "$file" fi done } # Set working directory setWorkDir() { if [[ -d "$MAP_FOLDER" ]]; then cd "$MAP_FOLDER" || exit 1 log_message "Using map folder \"$MAP_FOLDER\"... [OK]" else log_message "ERROR: Given folder \"$MAP_FOLDER\" does not exist" exit 2 fi } # Prompt for confirmation before overwriting prompt_for_confirmation() { read -p "File $1 exists. Overwrite? (y/n): " choice case "$choice" in y|Y ) log_message "Overwriting...";; n|N ) log_message "Skipping..."; exit 0;; * ) log_message "Invalid choice"; exit 1;; esac } # Show usage/help message show_help() { echo "Usage: InfoMap.sh [OPTIONS]" echo "Extract hex information from downloaded BMW / Mini / RR Maps" echo "Options:" echo " -d Specify the map folder to process." echo " -z Specify the archive file to process (zip, 7z, etc.)." echo " -f Specify the Info_Map.imp file directly." echo " -v Enable verbose mode." echo " -x Generate XML entry." echo " -b Batch process multiple folders or archives in the directory." echo " -h Show this help message." } ############# Main Program Starts ############# # Show help if no arguments are provided if [[ $# -eq 0 ]]; then show_help exit 0 fi POSITIONAL_ARGS=() while getopts ":d:z:f:xb:vh" option; do case $option in d) MAP_FOLDER="$OPTARG" ;; z) ARCHIVE_FILE="$OPTARG" ;; f) DIRECT_FILE="$OPTARG" ;; v) VERBOSE=1 ;; x) GENERATEXML=1 ;; b) process_batch "$OPTARG"; exit 0 ;; h) show_help; exit 0 ;; *) echo "Invalid option: -$OPTARG"; show_help; exit 1 ;; esac done shift $((OPTIND-1)) # Check dependencies check_dependencies # Processing logic based on provided arguments if [[ -n "$DIRECT_FILE" ]]; then validate_file "$DIRECT_FILE" INFOMAP_FILE="$DIRECT_FILE" elif [[ -n "$MAP_FOLDER" ]]; then setWorkDir processFolder elif [[ -n "$ARCHIVE_FILE" ]]; then processArchiveFile else log_message "No valid input provided" exit 1 fi # Parsing Info_Map.imp file parseInfoMapFile # Display map information showMapInfos # Generate XML entry if required if [[ $GENERATEXML -eq 1 ]]; then showLookupXMLEntry fi