#!/usr/bin/env bash # RR3 Asset Extraction Script - Cross-Platform # Extracts .z (ZLIB compressed) texture files from Real Racing 3 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(dirname "$SCRIPT_DIR")" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' CYAN='\033[0;36m' NC='\033[0m' # No Color echo -e "${CYAN}════════════════════════════════════════════════════════════${NC}" echo -e "${YELLOW} RR3 Asset Extraction Tool - Linux/Unix${NC}" echo -e "${CYAN}════════════════════════════════════════════════════════════${NC}" echo "" # Check if Python 3 is installed if ! command -v python3 &> /dev/null; then echo -e "${RED}ERROR: Python 3 is not installed!${NC}" echo "Please install Python 3 to continue." exit 1 fi # Check arguments if [ "$#" -lt 1 ]; then echo "Usage: $0 [output_folder]" echo "" echo "Examples:" echo " $0 sprites_0.etc.dds.z" echo " $0 sprites_0.etc.dds.z /path/to/output" exit 1 fi INPUT_FILE="$1" OUTPUT_DIR="${2:-$(dirname "$INPUT_FILE")}" # Validate input file if [ ! -f "$INPUT_FILE" ]; then echo -e "${RED}ERROR: Input file not found: $INPUT_FILE${NC}" exit 1 fi echo -e "${GREEN}Input file:${NC} $INPUT_FILE" echo -e "${GREEN}Output directory:${NC} $OUTPUT_DIR" echo "" # Create output directory if it doesn't exist mkdir -p "$OUTPUT_DIR" # Extract using Python python3 - "$INPUT_FILE" "$OUTPUT_DIR" << 'PYTHON_SCRIPT' import sys import os import zlib def main(): input_file = sys.argv[1] output_dir = sys.argv[2] print("Reading file...") with open(input_file, "rb") as f: data = f.read() out = b"" i = 0 found = 0 print("Scanning for ZLIB blocks...") # Scan for zlib blocks while i < len(data) - 2: if data[i] == 0x78 and data[i+1] in (0x9C, 0xDA, 0x01): try: d = zlib.decompress(data[i:]) out += d print(f" [+] Block {found} at {hex(i)}") found += 1 i += len(d) continue except: pass i += 1 if found == 0: print("ERROR: No valid zlib blocks found!") sys.exit(1) # Get output filename base = os.path.basename(input_file) if base.lower().endswith(".z"): base = base[:-2] output_file = os.path.join(output_dir, base) # Backup if exists if os.path.exists(output_file): bak = output_file + ".bak" if not os.path.exists(bak): os.rename(output_file, bak) print(f"Backup created: {bak}") # Write file with open(output_file, "wb") as f: f.write(out) print("") print(f"✅ Extraction complete!") print(f"Output: {output_file}") print(f"Blocks found: {found}") print(f"Size: {len(out):,} bytes") if __name__ == "__main__": main() PYTHON_SCRIPT echo "" echo -e "${GREEN}Done!${NC}"