Updates to patcher

This commit is contained in:
DazedAnon 2026-05-09 16:19:09 -05:00
parent 3f4ac69d88
commit bf344de85a
5 changed files with 361 additions and 178 deletions

View file

@ -1,11 +1,14 @@
@echo off
setlocal
pushd "%~dp0"
if not exist "gameupdate\patch.bat" (
echo ERROR: gameupdate\patch.bat not found!
pause
exit /b 1
)
call "gameupdate\patch.bat"
popd
endlocal
REM Copy GAMEUPDATE.bat to a new file
copy "gameupdate\patch.bat" "gameupdate\patch2.bat"
REM Run the new file
call "gameupdate\patch2.bat"
REM Delete the new file
del "gameupdate\patch2.bat"
endlocal
@echo on

View file

@ -5,11 +5,15 @@
## Future Patching
1. Run GAMEUPDATE.bat to auto patch.
2. Keep the whole `gameupdate` folder together when you ship the game—`patch.bat` and `patch-download.ps1` must sit side by side.
3. Optional: set `GAMEUPDATE_PROMPT_PWSH=1` before running `GameUpdate.bat` if you want users to be prompted to install PowerShell 7 via winget.
4. Optional: set `GAMEUPDATE_DL_ATTEMPTS` (default `2`) to control retries for API checks/downloads. Lower values fail faster; higher values tolerate flaky networks.
# Troubleshooting
**GAMEUPDATE.bat doesn't update and closes immediately**
1. Make sure your path doesn't contain any Japanese characters or lots of whitespace.
2. Make sure you actually have permissions in the folder
3. Auto-update calls GitLabs public HTTP API (`/api/v4/...`), not the web “Download ZIP” URL—no account or token is required for public patch repos.
For WOLF RPG games, if you downloaded the game off of DLSite, you will need to do some extra steps to patch it. This is because there is a "master" file called Data.wolf that will take priority over the english patch files. You will need this file to be a folder before patching will work.

View file

@ -0,0 +1,159 @@
#Requires -Version 5.1
param(
[Parameter(Mandatory = $true)]
[string]$GameRoot,
[Parameter(Mandatory = $true)]
[string]$StateFile
)
$ErrorActionPreference = 'Stop'
$exitCode = 1
if ($PSVersionTable.PSEdition -ne 'Core') {
try {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
}
catch {}
}
function Get-EnvInt {
param(
[Parameter(Mandatory = $true)][string]$Name,
[Parameter(Mandatory = $true)][int]$Default
)
$raw = [Environment]::GetEnvironmentVariable($Name)
if ([string]::IsNullOrWhiteSpace($raw)) { return $Default }
$parsed = 0
if ([int]::TryParse([string]$raw, [ref]$parsed) -and $parsed -gt 0) { return $parsed }
return $Default
}
function Invoke-WithRetry {
param(
[Parameter(Mandatory = $true)][scriptblock]$Action,
[Parameter(Mandatory = $true)][string]$Name,
[int]$Attempts = 2,
[int]$DelaySeconds = 2
)
$lastErr = $null
for ($i = 1; $i -le $Attempts; $i++) {
try {
return & $Action
}
catch {
$lastErr = $_
if ($i -lt $Attempts) {
Write-Host ("{0} failed ({1}/{2}), retrying..." -f $Name, $i, $Attempts)
Start-Sleep -Seconds $DelaySeconds
}
}
}
throw $lastErr
}
function Download-WithIwrSpeedProgress {
param(
[Parameter(Mandatory = $true)][string]$Url,
[Parameter(Mandatory = $true)][string]$OutFile,
[Parameter(Mandatory = $true)][hashtable]$Headers
)
if (Test-Path -LiteralPath $OutFile) {
Remove-Item -LiteralPath $OutFile -Force
}
# Fast path: let Invoke-WebRequest handle transfer and progress internally.
# Custom stream/polling progress gives richer stats but adds measurable overhead.
$prevPref = $ProgressPreference
try {
$ProgressPreference = 'Continue'
Invoke-WebRequest -Uri $Url -OutFile $OutFile -Headers $Headers -UseBasicParsing
}
finally {
$ProgressPreference = $prevPref
}
}
try {
Set-Location -LiteralPath $GameRoot
if (-not $env:GU_USERNAME -or -not $env:GU_REPO -or -not $env:GU_BRANCH) {
throw 'PATCH_ERR:CONFIG:patch.bat must set GU_USERNAME, GU_REPO, and GU_BRANCH.'
}
$id = [uri]::EscapeDataString($env:GU_USERNAME + '/' + $env:GU_REPO)
$branch = [uri]::EscapeDataString($env:GU_BRANCH)
$ua = 'DazedMTL-Patcher-1.0'
$headers = @{ 'User-Agent' = $ua }
$dlAttempts = Get-EnvInt -Name 'GAMEUPDATE_DL_ATTEMPTS' -Default 2
$latestSha = Invoke-WithRetry -Name 'Resolve latest patch SHA' -Attempts $dlAttempts -Action {
(Invoke-RestMethod -Uri ("https://gitgud.io/api/v4/projects/$id/repository/branches/$branch") -Headers $headers).commit.id
}
if (-not $latestSha) { throw 'PATCH_ERR:API:Latest commit SHA response was empty.' }
$latestSha = ([string]$latestSha).Trim()
$previousSha = ''
if (Test-Path -LiteralPath $StateFile) {
$previousSha = (Get-Content -LiteralPath $StateFile -Raw).Trim()
} else {
Write-Host 'Previous SHA hash not found. Assuming first time patching...'
}
if ($previousSha -eq $latestSha) {
$exitCode = 10
return
}
Write-Host 'Update found! Patching...'
Write-Host 'Downloading latest patch... (backend: iwr, GitLab API)'
$zipPath = Join-Path $PWD.Path 'repo.zip'
$stage = Join-Path $PWD.Path '_patch_extract_tmp'
$archiveSha = [uri]::EscapeDataString($latestSha)
$archiveUrl = "https://gitgud.io/api/v4/projects/$id/repository/archive.zip?sha=$archiveSha"
$dlSw = [System.Diagnostics.Stopwatch]::StartNew()
Invoke-WithRetry -Name 'Download archive with Invoke-WebRequest' -Attempts $dlAttempts -Action {
Download-WithIwrSpeedProgress -Url $archiveUrl -OutFile $zipPath -Headers $headers
} | Out-Null
$dlSw.Stop()
$bytes = (Get-Item -LiteralPath $zipPath).Length
$secs = [Math]::Max($dlSw.Elapsed.TotalSeconds, 0.001)
$mbps = ($bytes / 1MB) / $secs
Write-Host ("Download complete via iwr: {0:N1} MB in {1:N1}s ({2:N1} MB/s)" -f ($bytes / 1MB), $secs, $mbps)
$fs = [System.IO.File]::OpenRead($zipPath)
try {
$hdr = New-Object byte[] 4
if ($fs.Read($hdr, 0, 4) -lt 4 -or $hdr[0] -ne 0x50 -or $hdr[1] -ne 0x4B) {
throw 'PATCH_ERR:ZIP:Download is not a valid ZIP (error page or empty file).'
}
}
finally {
$fs.Dispose()
}
if (Test-Path -LiteralPath $stage) { Remove-Item -LiteralPath $stage -Recurse -Force }
New-Item -ItemType Directory -Path $stage | Out-Null
try {
Expand-Archive -LiteralPath $zipPath -DestinationPath $stage -Force
$dirs = @(Get-ChildItem -LiteralPath $stage -Directory)
if ($dirs.Count -ne 1) {
throw ('PATCH_ERR:ZIP:Expected one root folder in archive, found {0}.' -f $dirs.Count)
}
Copy-Item -Path (Join-Path $dirs[0].FullName '*') -Destination $PWD.Path -Recurse -Force
}
finally {
if (Test-Path -LiteralPath $stage) { Remove-Item -LiteralPath $stage -Recurse -Force }
}
Set-Content -LiteralPath $StateFile -Value $latestSha -Encoding Ascii
$exitCode = 0
}
catch {
Write-Host ''
Write-Host ($_.Exception.Message)
if ($_.InvocationInfo.PositionMessage) { Write-Host $_.InvocationInfo.PositionMessage }
$exitCode = 1
}
exit $exitCode

View file

@ -29,41 +29,38 @@ echo Using root directory: "%ROOT_DIR%"
echo Using config: "%CONFIG_FILE%"
echo Checking for pwsh...
set _my_shell=pwsh
REM Check if pwsh.exe exists
set "_my_shell=pwsh"
where /q !_my_shell!
if !errorlevel! neq 0 (
echo pwsh not found.
echo.
echo PowerShell 7 ^(pwsh^) is faster and recommended.
set /p "INSTALL_PWSH=Would you like to install it now via winget? (Y/N): "
if /I "!INSTALL_PWSH!"=="Y" (
echo Installing PowerShell 7 via winget...
winget install --id Microsoft.PowerShell --source winget --accept-package-agreements --accept-source-agreements
if !errorlevel! neq 0 (
echo Install failed or winget not available. Falling back to powershell...
set _my_shell=powershell
if /I "%GAMEUPDATE_PROMPT_PWSH%"=="1" (
echo.
set /p "INSTALL_PWSH=PowerShell 7 is faster. Install now via winget? (Y/N): "
if /I "!INSTALL_PWSH!"=="Y" (
echo Installing PowerShell 7 via winget...
winget install --id Microsoft.PowerShell --source winget --accept-package-agreements --accept-source-agreements
where /q pwsh
if !errorlevel! equ 0 (
set "_my_shell=pwsh"
echo PowerShell 7 installed; using pwsh.
) else (
echo Install failed or unavailable; falling back to powershell.
set "_my_shell=powershell"
)
) else (
echo PowerShell 7 installed successfully.
echo Please re-run GameUpdate.bat to use pwsh.
pause
exit /b 0
echo Skipping install; falling back to powershell.
set "_my_shell=powershell"
)
) else (
echo Skipping install. Falling back to powershell...
set _my_shell=powershell
echo Tip: Set GAMEUPDATE_PROMPT_PWSH=1 to offer PowerShell 7 install.
echo Falling back to powershell...
set "_my_shell=powershell"
)
REM Check if powershell.exe exists
echo Checking for powershell...
where /q !_my_shell!
if !errorlevel! neq 0 (
echo.Error: Powershell not found!
echo ERROR: Neither pwsh nor powershell was found.
pause
exit /B 1
) else (
echo powershell found.
exit /b 1
)
) else (
echo pwsh found.
@ -85,6 +82,28 @@ for /f "usebackq tokens=1,2 delims==" %%a in ("%CONFIG_FILE%") do (
if "%%a"=="branch" set "branch=%%b"
)
REM Validate required config keys early for clearer errors
if "%username%"=="" (
echo ERROR: 'username=' is missing in gameupdate\patch-config.txt
pause
exit /b 1
)
if "%repo%"=="" (
echo ERROR: 'repo=' is missing in gameupdate\patch-config.txt
pause
exit /b 1
)
if "%branch%"=="" (
echo ERROR: 'branch=' is missing in gameupdate\patch-config.txt
pause
exit /b 1
)
REM For PowerShell (proper URL encoding; avoids cmd %% pitfalls)
set "GU_USERNAME=%username%"
set "GU_REPO=%repo%"
set "GU_BRANCH=%branch%"
REM --------------------------------------------------------
REM PRE-SETUP: Ensure SRPG data and patch structure exists
REM Run Steps 1 and 2 BEFORE pulling repo patch to avoid overwriting updates
@ -144,83 +163,31 @@ if exist "%ROOT_DIR%\data.dts" (
echo [Pre-Setup] data.dts not found; skipping pre-setup SRPG steps.
)
REM Get the latest hash
echo "Getting latest commit SHA hash"
!_my_shell! -Command "(Invoke-RestMethod -Uri 'https://gitgud.io/api/v4/projects/%username%%%2F%repo%/repository/branches/%branch%').commit.id" > "%ROOT_DIR%\latest_patch_sha.txt"
REM Read the latest SHA from the file
set /p latest_patch_sha=<"%ROOT_DIR%\latest_patch_sha.txt"
REM Check if previous_patch_sha.txt exists in gameupdate
if not exist "%SCRIPT_DIR%previous_patch_sha.txt" (
echo "Previous SHA hash not found!"
echo "Assuming first time patching..."
goto download_extract
)
REM Read the stored SHA from previous check
set /p previous_patch_sha=<"%SCRIPT_DIR%previous_patch_sha.txt"
REM Trim whitespace from SHA strings
set "previous_patch_sha=%previous_patch_sha: =%"
set "latest_patch_sha=%latest_patch_sha: =%"
REM Compare trimmed SHAs
if "%latest_patch_sha%" neq "%previous_patch_sha%" (
echo "Update found! Patching..."
goto download_extract
) else (
echo "Patch is up to date."
)
REM Delete latest_patch_sha.txt
del "%ROOT_DIR%\latest_patch_sha.txt"
endlocal
pause
exit /b
:download_extract
REM Escape single quotes in paths
set "escaped_root=%ROOT_DIR:'=''%"
REM Download zip file to root via GitLab API (bypasses Cloudflare DDoS protection)
echo "Downloading latest patch..."
!_my_shell! -Command "Set-Location -LiteralPath '%escaped_root%'; $ProgressPreference = 'SilentlyContinue'; Invoke-WebRequest -Uri 'https://gitgud.io/api/v4/projects/%username%%%2F%repo%/repository/archive.zip?sha=%branch%' -Headers @{'User-Agent'='git/2.0'} -OutFile 'repo.zip'"
if !errorlevel! neq 0 (
REM Download/extract via patch-download.ps1 (IWR-based); Bypass avoids ExecutionPolicy prompts
if not exist "%SCRIPT_DIR%patch-download.ps1" (
echo ERROR: patch-download.ps1 not found next to patch.bat in the gameupdate folder.
pause
exit /b
exit /b 1
)
REM Extract contents, overwriting conflicts into root
echo "Extracting..."
!_my_shell! -Command "Set-Location -LiteralPath '%escaped_root%'; $ProgressPreference = 'SilentlyContinue'; Expand-Archive -Path '.\repo.zip' -DestinationPath '.' -Force"
if !errorlevel! neq 0 (
echo Extraction failed!
del "%ROOT_DIR%\repo.zip"
rmdir /s /q "%ROOT_DIR%\%repo%-%branch%"
!_my_shell! -NoProfile -ExecutionPolicy Bypass -File "%SCRIPT_DIR%patch-download.ps1" -GameRoot "%ROOT_DIR%" -StateFile "%SCRIPT_DIR%previous_patch_sha.txt"
set "PATCH_DL_EXIT=!errorlevel!"
if "!PATCH_DL_EXIT!"=="10" (
echo Patch is up to date.
endlocal
pause
exit /b
exit /b 0
)
if not "!PATCH_DL_EXIT!"=="0" (
echo Download or extraction failed!
if exist "%ROOT_DIR%\repo.zip" del "%ROOT_DIR%\repo.zip"
if exist "%ROOT_DIR%\_patch_extract_tmp" rmdir /s /q "%ROOT_DIR%\_patch_extract_tmp"
pause
exit /b 1
)
echo "Applying patch..."
REM API zip uses a different folder name (repo-branch-sha), find it dynamically
set "EXTRACTED_DIR="
for /d %%D in ("%ROOT_DIR%\%repo%-*") do set "EXTRACTED_DIR=%%D"
if not defined EXTRACTED_DIR (
echo Patch application failed - extracted folder not found!
del "%ROOT_DIR%\repo.zip"
pause
exit /b
)
robocopy "!EXTRACTED_DIR!" "%ROOT_DIR%" /s /e /xf "GameUpdate.bat" "patch.bat"
if !errorlevel! geq 8 (
echo Patch application failed!
del "%ROOT_DIR%\repo.zip"
rmdir /s /q "!EXTRACTED_DIR!"
pause
exit /b
)
REM Files merged by Copy-Item above
REM --------------------------------------------------------
REM POST-APPLY: Run Steps 3 and 4 after patch files are merged
REM 3) Apply Patch to data\project.dat
@ -265,10 +232,7 @@ if exist "%ROOT_DIR%\data.dts" (
REM Clean up
echo "Cleaning up..."
del "%ROOT_DIR%\repo.zip"
if defined EXTRACTED_DIR rmdir /s /q "!EXTRACTED_DIR!"
del "%ROOT_DIR%\latest_patch_sha.txt"
REM Store latest SHA for next check in gameupdate
echo %latest_patch_sha% > "%SCRIPT_DIR%previous_patch_sha.txt"
if exist "%ROOT_DIR%\_patch_extract_tmp" rmdir /s /q "%ROOT_DIR%\_patch_extract_tmp"
endlocal
pause
exit /b

View file

@ -1,10 +1,13 @@
#!/bin/bash
set -e
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(pwd)"
CONFIG_FILE="$SCRIPT_DIR/patch-config.txt"
STATE_FILE="$SCRIPT_DIR/previous_patch_sha.txt"
GITGUD_API="https://gitgud.io/api/v4"
API_HEADERS=( -H "User-Agent: GameUpdate/1.0" )
check_dependency() {
if ! command -v "$1" > /dev/null 2>&1; then
@ -32,11 +35,61 @@ echo "Root directory: $ROOT_DIR"
echo "Config file path: $CONFIG_FILE"
# Read configuration from file
# shellcheck disable=SC1090
. "$CONFIG_FILE"
if [ -z "${username:-}" ]; then
echo "ERROR: 'username=' is missing in gameupdate/patch-config.txt"
exit 1
fi
if [ -z "${repo:-}" ]; then
echo "ERROR: 'repo=' is missing in gameupdate/patch-config.txt"
exit 1
fi
if [ -z "${branch:-}" ]; then
echo "ERROR: 'branch=' is missing in gameupdate/patch-config.txt"
exit 1
fi
RETRIES="${GAMEUPDATE_DL_ATTEMPTS:-2}"
if ! [[ "$RETRIES" =~ ^[1-9][0-9]*$ ]]; then
RETRIES=2
fi
retry_cmd() {
local name="$1"
shift
local attempt=1
while true; do
if "$@"; then
return 0
fi
if [ "$attempt" -ge "$RETRIES" ]; then
echo "$name failed after $attempt attempt(s)."
return 1
fi
echo "$name failed ($attempt/$RETRIES), retrying..."
attempt=$((attempt + 1))
sleep 2
done
}
project_enc=$(jq -nr --arg ns "$username" --arg rp "$repo" '$ns + "/" + $rp | @uri')
branch_enc=$(jq -nr --arg b "$branch" '$b | @uri')
# Get the latest hash
echo "Getting latest commit SHA hash"
latest_patch_sha=$(curl -s "https://gitgud.io/api/v4/projects/$username%2F$repo/repository/branches/$branch" | jq -r '.commit.id')
latest_patch_sha="$(
retry_cmd "Resolve latest patch SHA" \
curl -fsSL "${API_HEADERS[@]}" \
"${GITGUD_API}/projects/${project_enc}/repository/branches/${branch_enc}" \
| jq -r '.commit.id'
)"
latest_patch_sha="$(printf '%s' "$latest_patch_sha" | tr -d '[:space:]')"
if [ -z "$latest_patch_sha" ] || [ "$latest_patch_sha" = "null" ]; then
echo "PATCH_ERR:API:Latest commit SHA response was empty."
exit 1
fi
# --------------------------------------------------------
# PRE-SETUP: Ensure SRPG data and patch structure exists
@ -49,92 +102,93 @@ if [ -f "$ROOT_DIR/data.dts" ]; then
if [ -f "$UNPACKER" ]; then
echo "[Pre-Setup] Running SRPG_Unpacker preparation steps..."
# Step 1: Unpack (once)
if [ ! -d "$ROOT_DIR/data" ]; then
if [ -f "$ROOT_DIR/data.dts" ]; then
echo "[Pre-Setup] Step 1: Unpacking data.dts -> data"
( cd "$ROOT_DIR" && "$UNPACKER" -o data data.dts ) || echo "[Pre-Setup] ERROR: Unpack failed."
# Step 1: Unpack (once) — mirror patch.bat: unpack if no data/ or no data/project.dat
if [ ! -d "$ROOT_DIR/data" ] || [ ! -f "$ROOT_DIR/data/project.dat" ]; then
if [ -f "$ROOT_DIR/data.dts" ]; then
echo "[Pre-Setup] Step 1: Unpacking data.dts -> data"
( cd "$ROOT_DIR" && "$UNPACKER" -o data data.dts ) || echo "[Pre-Setup] ERROR: Unpack failed."
else
echo "[Pre-Setup] Step 1: Skipping unpack (no data folder and no data.dts found)."
fi
else
echo "[Pre-Setup] Step 1: Skipping unpack (no data folder and no data.dts found)."
echo "[Pre-Setup] Step 1: data folder exists; skipping unpack."
fi
else
echo "[Pre-Setup] Step 1: data folder exists; skipping unpack."
fi
# Step 2: Create Patch (once)
if [ ! -d "$ROOT_DIR/patch" ]; then
if [ -f "$ROOT_DIR/data/project.dat" ]; then
echo "[Pre-Setup] Step 2: Creating patch from data/project.dat"
( cd "$ROOT_DIR" && "$UNPACKER" ./data/project.dat -c ) || echo "[Pre-Setup] ERROR: Create Patch failed."
else
echo "[Pre-Setup] Step 2: Skipping create patch (data/project.dat not found)."
fi
# Step 2: Create Patch (once)
if [ ! -d "$ROOT_DIR/patch" ]; then
if [ -f "$ROOT_DIR/data/project.dat" ]; then
echo "[Pre-Setup] Step 2: Creating patch from data/project.dat"
( cd "$ROOT_DIR" && "$UNPACKER" ./data/project.dat -c ) || echo "[Pre-Setup] ERROR: Create Patch failed."
else
echo "[Pre-Setup] Step 2: Skipping create patch (data/project.dat not found)."
fi
else
echo "[Pre-Setup] Step 2: patch folder exists; skipping create."
fi
else
echo "[Pre-Setup] SRPG_Unpacker.exe not found in root; skipping pre-setup steps."
fi
else
echo "[Pre-Setup] data.dts not found; skipping pre-setup SRPG steps."
echo "[Pre-Setup] SRPG_Unpacker.exe not found in root; skipping pre-setup steps."
fi
else
echo "[Pre-Setup] data.dts not found; skipping pre-setup SRPG steps."
fi
download_extract() {
# Download zip file into root via GitLab API (bypasses Cloudflare DDoS protection)
echo "Downloading latest patch..."
curl -sL -A "git/2.0" "https://gitgud.io/api/v4/projects/$username%2F$repo/repository/archive.zip?sha=$branch" -o "$ROOT_DIR/repo.zip"
if [ $? -ne 0 ]; then
archive_sha_enc=$(jq -nr --arg s "$latest_patch_sha" '$s | @uri')
if ! retry_cmd "Download archive with curl" \
curl -fSL --progress-bar "${API_HEADERS[@]}" \
"${GITGUD_API}/projects/${project_enc}/repository/archive.zip?sha=${archive_sha_enc}" \
-o "$ROOT_DIR/repo.zip"; then
echo "Download failed!"
rm -f "$ROOT_DIR/repo.zip"
rm -rf "$ROOT_DIR/$repo-$branch"
return 1
fi
# Extract contents, overwriting conflicts into root
TMP_EX=$(mktemp -d)
echo "Extracting..."
unzip -qo "$ROOT_DIR/repo.zip" -d "$ROOT_DIR"
if [ $? -ne 0 ]; then
if ! unzip -qo "$ROOT_DIR/repo.zip" -d "$TMP_EX"; then
echo "Extraction failed!"
rm -rf "$TMP_EX"
rm -f "$ROOT_DIR/repo.zip"
return 1
fi
inner=""
for d in "$TMP_EX"/*; do
if [ -d "$d" ]; then
inner="$d"
break
fi
done
if [ -z "$inner" ]; then
echo "Archive had no root folder!"
rm -rf "$TMP_EX"
rm -f "$ROOT_DIR/repo.zip"
rm -rf "$ROOT_DIR/$repo-$branch"
return 1
fi
echo "Applying patch..."
# API zip uses a different folder name (repo-branch-sha), find it dynamically
EXTRACTED_DIR=$(find "$ROOT_DIR" -maxdepth 1 -type d -name "${repo}-*" | head -1)
if [ -z "$EXTRACTED_DIR" ]; then
echo "Patch application failed - extracted folder not found!"
rm -f "$ROOT_DIR/repo.zip"
return 1
fi
cp -r "$EXTRACTED_DIR/"* "$ROOT_DIR/"
if [ $? -ne 0 ]; then
if ! cp -r "$inner"/* "$ROOT_DIR/"; then
echo "Patch application failed!"
rm -rf "$TMP_EX"
rm -f "$ROOT_DIR/repo.zip"
rm -rf "$ROOT_DIR/$repo-$branch"
return 1
fi
rm -rf "$TMP_EX"
echo "Cleaning up..."
rm -f "$ROOT_DIR/repo.zip"
[ -n "$EXTRACTED_DIR" ] && rm -rf "$EXTRACTED_DIR"
rm -f "$ROOT_DIR/latest_patch_sha.txt"
# Store latest SHA for next check in gameupdate
echo "$latest_patch_sha" > "$SCRIPT_DIR/previous_patch_sha.txt"
# --------------------------------------------------------
# POST-APPLY: Run Steps 3 and 4 after patch files are merged
# --------------------------------------------------------
UNPACKER="$ROOT_DIR/SRPG_Unpacker.exe"
if [ -f "$ROOT_DIR/data.dts" ]; then
if [ -f "$UNPACKER" ]; then
echo "Running SRPG_Unpacker apply/pack steps..."
# --------------------------------------------------------
# POST-APPLY: Run Steps 3 and 4 after patch files are merged
# 3) Apply Patch to data/project.dat
# 4) Pack data back into data.dts
# --------------------------------------------------------
UNPACKER="$ROOT_DIR/SRPG_Unpacker.exe"
if [ -f "$ROOT_DIR/data.dts" ]; then
if [ -f "$UNPACKER" ]; then
echo "Running SRPG_Unpacker apply/pack steps..."
# Step 3: Apply Patch
if [ -f "$ROOT_DIR/data/project.dat" ]; then
echo "Step 3: Applying patch to data/project.dat"
( cd "$ROOT_DIR" && "$UNPACKER" ./data/project.dat -a ) || echo "ERROR: Apply Patch failed."
@ -142,31 +196,30 @@ download_extract() {
echo "ERROR: data/project.dat not found; cannot apply patch."
fi
# Step 4: Pack
if [ -d "$ROOT_DIR/data" ]; then
echo "Step 4: Packing data -> data.dts"
( cd "$ROOT_DIR" && "$UNPACKER" -o data.dts data ) || echo "WARNING: Pack failed."
else
echo "Step 4: Skipping pack (data folder not found)."
fi
else
echo "SRPG_Unpacker.exe not found in root; skipping SRPG patch steps."
fi
else
echo "data.dts not found; skipping SRPG patch steps."
fi
else
echo "Step 4: Skipping pack (data folder not found)."
fi
else
echo "SRPG_Unpacker.exe not found in root; skipping SRPG patch steps."
fi
else
echo "data.dts not found; skipping SRPG patch steps."
fi
echo "$latest_patch_sha" > "$STATE_FILE"
}
# Check if previous_patch_sha.txt exists in gameupdate
if [ ! -f "$SCRIPT_DIR/previous_patch_sha.txt" ]; then
if [ ! -f "$STATE_FILE" ]; then
echo "Previous SHA hash not found!"
echo "Assuming first time patching..."
download_extract
else
# Read the stored SHA from previous check
previous_patch_sha=$(cat "$SCRIPT_DIR/previous_patch_sha.txt")
previous_patch_sha=$(tr -d '[:space:]' < "$STATE_FILE")
# Compare trimmed SHAs
if [ "$latest_patch_sha" != "$previous_patch_sha" ]; then
echo "Update found! Patching..."
download_extract