wackman/init.sh
2025-10-23 20:58:01 +02:00

206 lines
No EOL
7.2 KiB
Bash
Executable file

#!/bin/bash
set -e
source .config
workdir=${WORKDIR:-/tmp/wacca}
version=${VERSION:-3.07.01}
airgap=${AIRGAP:-false}
check_prereqs () {
tools=("vhdimount" "umu-run" "fsdecrypt" "aria2c" "udisksctl")
echo "Checking for required tools..."
echo "=============================="
all_installed=true
for tool in "${tools[@]}"; do
if command -v "$tool" &> /dev/null; then
echo -e "\033[0;32m✓\033[0m $tool is installed"
else
echo -e "\033[0;31m✗\033[0m $tool is NOT installed"
all_installed=false
fi
done
echo "=============================="
if [ "$all_installed" != true ]; then
echo "Some tools are missing :("
if [ "$ignore_prereqs" = true ]; then
echo "Ignoring prerequisites"
else
exit 1
fi
fi
}
# GET NEEDED APPS FROM $VERSION
get_required_app () {
apps=""
while IFS=',' read -r version url; do
apps+="$url,"
if [[ "$version" == "$VERSION" ]]; then
break
fi
done < <(grep "$(echo "^$VERSION" | cut -c1-4)" imagestore/index.csv)
}
import_from_ins () {
result=$(blkid | grep SEGA_INS | head -n 1 | cut -d: -f1 )
if [ -n "${result:-}" ]; then
echo "Checking SEGA_INS for SDFE .app files..."
udisksctl mount --block-device $result
mount_point=$(findmnt -n -o TARGET $result)
for file in $mount_point/SDFE*.app; do
basename=$(basename $file)
if [ -f "imagestore/app/$basename" ]; then
echo "$basename: File already present on target, skipping."
else
echo "$basename: Adding file."
pv $file > imagestore/app/$basename
fi
done
udisksctl unmount --block-device $result
else
echo "SEGA_INS not found, skipping."
fi
}
extract_apps () {
missingapps=()
mkdir -p imagestore/vhd
for url in ${apps//,/ }; do
local file=$(basename "$url")
local vhd=$(basename "$url" | sed -E "s/.app/.vhd/")
if [ -f imagestore/app/$file ]; then
echo "Found $file"
if [ -f imagestore/vhd/$vhd ]; then
echo "Found $vhd"
else
echo "Decrypting $file"
fsdecrypt imagestore/app/$file
mv imagestore/app/$vhd imagestore/vhd/
fi
else
if [ ! -f imagestore/vhd/$vhd ]; then
if [ "$airgap" = false ]; then
echo "Downloading $file"
aria2c -x 8 -j 8 -o imagestore/app/$file $url
echo "Decrypting $file"
fsdecrypt imagestore/app/$file
mv imagestore/app/$vhd imagestore/vhd/
else
echo $file
missingapps+=("$file")
fi
fi
fi
done
if [ ${#missingapps[@]} -gt 0 ]; then
echo "ERROR: Missing following .app files for specified version:"
for app in ${missingapps[@]}; do
echo "- "$app
done
exit 2
fi
}
patchbin () {
# local targetvhd="$1"
# local tmp=$(mktemp -u)
# dd if=$targetvhd of=$tmp bs=1 count=576
# dd if=TEST.vhd of=$tmp bs=1 skip=575 seek=576 count=80
# dd if=$tmp of=$targetvhd bs=1 conv=notrunc
# echo -n $(basename $1) | iconv -f UTF-8 -t UTF-16BE | dd of=test
for url in ${apps//,/ }; do
local file=$(basename $url)
IFS='_' read gameid version date vhdpos parentversion <<< "${file%.app}"
if [[ "$vhdpos" != "0" ]]; then
local vhd=$(basename "$url" | sed -E "s/.app/.vhd/")
local input=$(vhdiinfo imagestore/vhd/$vhd)
local identifier=$(echo "$input" | grep -i "Identifier" | head -1 | awk '{print $NF}')
local parent_identifier=$(echo "$input" | grep -i "Parent identifier" | awk '{print $NF}')
local parent_filename=$(echo "$input" | grep -i "Parent filename" | awk -F': ' '{print $2}')
echo "Checking $vhd parent"
if [[ ! "$parent_filename" =~ ^SDFE ]]; then
echo "$vhd Parent filename incorrect"
local new_parent_filename=$(grep "^$parentversion" imagestore/index.csv | cut -d',' -f2 | xargs basename | sed -E "s/.app/.vhd/")
local len=${#new_parent_filename}
local result=$(((len * 2)))
echo "Writing parent filename $new_parent_filename to $vhd"
echo -n $new_parent_filename | iconv -f UTF-8 -t UTF-16BE | dd of=imagestore/vhd/$vhd seek=576 bs=1 conv=notrunc
echo -n $new_parent_filename | iconv -f UTF-8 -t UTF-16BE | dd of=imagestore/vhd/$vhd seek=4096 bs=1 conv=notrunc
if [ $result -lt 80 ]; then
local remainder=$((80 - result))
dd if=/dev/zero of=imagestore/vhd/$vhd seek=$((576 + result)) bs=1 count=$remainder conv=notrunc
dd if=/dev/zero of=imagestore/vhd/$vhd seek=$((4096 + result)) bs=1 count=$remainder conv=notrunc
fi
fi
fi
done
}
mount () {
if [ "$MOUNT_AS_ROOT" = false ]; then
sudo=""
else
sudo="sudo"
fi
local vhdpath=$(grep "^$version" imagestore/index.csv | cut -d',' -f2 | xargs basename | sed -E "s/.app/.vhd/")
mkdir -p $workdir/$version/{lower,upper,game,work} || true
if [ -z "$($sudo ls -A "$workdir/$version/dev")" ]; then
mkdir -p $workdir/$version/dev || true
$sudo vhdimount imagestore/vhd/$vhdpath $workdir/$version/dev
fi
if ! df -h | grep -q "$workdir/$version/lower"; then
$sudo mount -t ntfs -o offset=$((2048*512)),uid=$(id -u),gid=$(id -g) $($sudo find $workdir/$version/dev -maxdepth 1 -type f | sort -V | tail -1) $workdir/$version/$profile/lower
fi
if ! df -h | grep -q "$workdir/$version/game"; then
$sudo mount overlay -t overlay -o lowerdir=$workdir/$version/lower,upperdir=$workdir/$version/upper,workdir=$workdir/$version/work $workdir/$version/game
fi
}
apply_patches () {
# Temp shit
icf="https://archive.org/download/WACCA/EXP/3.00.00%20USB/SDFE_ACA.icf"
dir=$workdir/$version
cd ./patches
for script in $(ls -1v 2>/dev/null); do
[ -f "$script" ] && [ -r "$script" ] || continue
if ! grep -qxF "$script" "$dir/patches"; then
echo -e "\033[0;34m=== Applying: $script ===\033[0m"
# Create a named pipe for real-time output
local pipe=$(mktemp -u)
mkfifo "$pipe"
# Execute the script with real-time output
if (source "$script" 2>&1 | while IFS= read -r line; do
echo "[$script] $line"
done); then
echo -e "\033[0;32m=== Successfully applied: $script ===\033[0m"
echo "$script" >> $dir/patches
else
exit_code=$?
echo -e "\033[0;31m=== Failed: $script (exit code: $exit_code) ===\033[0m"
fi
else
echo -e "\033[0;33m=== Skipping: $script ===\033[0m"
fi
# Clean up the pipe
rm -f "$pipe"
echo
done
}
check_prereqs
get_required_app
import_from_ins
extract_apps
patchbin
mount
apply_patches