Skip to content

Instantly share code, notes, and snippets.

@dotaxis
Last active June 6, 2026 20:48
Show Gist options
  • Select an option

  • Save dotaxis/1ad1c64baa7ad9c1dabcb255ea6257ae to your computer and use it in GitHub Desktop.

Select an option

Save dotaxis/1ad1c64baa7ad9c1dabcb255ea6257ae to your computer and use it in GitHub Desktop.
Memoria Patcher for Linux
#!/bin/bash
echo "WARNING!"
echo "A legitimate copy of FINAL FANTASY IX needs to be installed on this device!"
echo
echo "If you face issues with this installer, please pay us a visit on Discord:"
echo "https://discord.gg/tsunamods-community-277610501721030656"
echo "You can find me (Dot) in the #ff9-linux channel!"
echo
if ! awk --version 2>/dev/null | grep -q "GNU Awk"; then
echo "Error: GNU Awk (gawk) is not the active awk. Please install it before running this script again."
exit 1
fi
echo "Press Enter to continue."
read
getSteamLibrary() {
local app_id="$1"
local steam_dir=""
if [[ -f "${HOME}/.steam/root/steamapps/libraryfolders.vdf" ]]; then
steam_dir="${HOME}/.steam/root"
elif [[ -f "${HOME}/.local/share/Steam/steamapps/libraryfolders.vdf" ]]; then
steam_dir="${HOME}/.local/share/Steam"
elif [[ -f "${HOME}/.var/app/com.valvesoftware.Steam/.steam/root/steamapps/libraryfolders.vdf" ]]; then
steam_dir="${HOME}/.var/app/com.valvesoftware.Steam/.steam/root"
else
echo ""
return 1
fi
local path=$(
awk -v app_id="$app_id" '
/^[[:space:]]*"[0-9]+"$/ {
in_block = 1;
block = $0;
next;
}
in_block {
block = block "\n" $0;
if ($0 ~ /^\s*}/) {
in_block = 0;
if (block ~ app_id) {
match(block, /"path"\s+"([^"]+)"/, arr);
print arr[1];
exit;
}
}
}
' "${steam_dir}/steamapps/libraryfolders.vdf"
)
echo "$path"
}
getHeroicLibrary() {
local app_id=$1
local config_dir=""
if [[ -d "${HOME}/.config/heroic" ]]; then
config_dir="${HOME}/.config/heroic"
elif [[ -d "${HOME}/.var/app/com.heroicgameslauncher.hgl/config/heroic" ]]; then
config_dir="${HOME}/.var/app/com.heroicgameslauncher.hgl/config/heroic"
elif [[ -d "/var/lib/flatpak/app/com.heroicgameslauncher.hgl/current/active/files/config/heroic" ]]; then
config_dir="/var/lib/flatpak/app/com.heroicgameslauncher.hgl/current/active/files/config/heroic"
else
echo "||"
return 1
fi
local runner=$(
awk '
/"bin"[[:space:]]*:[[:space:]]*"/ {
match($0, /"bin"[[:space:]]*:[[:space:]]*"([^"]*)"/, arr)
print arr[1]
exit
}
' "${config_dir}/GamesConfig/${app_id}.json"
)
local prefix=$(
awk '
/"winePrefix"[[:space:]]*:[[:space:]]*"/ {
match($0, /"winePrefix"[[:space:]]*:[[:space:]]*"([^"]*)"/, arr)
print arr[1]
exit
}
' "${config_dir}/GamesConfig/${app_id}.json"
)
local path=$(
awk -v game_id="$app_id" '
/"install_path"[[:space:]]*:[[:space:]]*"/ {
match($0, /"install_path"[[:space:]]*:[[:space:]]*"([^"]*)"/, path)
install = path[1]
}
/"appName"[[:space:]]*:[[:space:]]*"/ {
match($0, /"appName"[[:space:]]*:[[:space:]]*"([^"]*)"/, app)
if (app[1] == game_id) {
print install
exit
}
}
' "${config_dir}/gog_store/installed.json"
)
echo "$runner|$prefix|$path"
}
downloadDependency() {
local REPO=$1
local FILTER=$2
local RETURN_VARIABLE=$3
local RELEASE_URL=$(
curl -s https://api.github.com/repos/"$REPO"/releases/tags/canary \
| grep "browser_download_url.$FILTER" \
| head -1 \
| cut -d : -f 2,3 \
| tr -d \")
local FILENAME="$(basename "$RELEASE_URL")"
if [ -f "$FILENAME" ]; then
echo "$FILENAME is ready to be installed."
else
echo "$FILENAME not found. Downloading..."
curl -#SL -o $FILENAME $RELEASE_URL
fi
eval "${RETURN_VARIABLE}=\"$FILENAME\""
}
IS_STEAM=false
IS_HEROIC=false
# Check for FF9
echo -n "Checking if FF9 is installed in Heroic Games Launcher... "
RESULT=$(getHeroicLibrary 1375008492)
RUNNER=$(echo "$RESULT" | cut -d'|' -f1)
PREFIX=$(echo "$RESULT" | cut -d'|' -f2)
GAMEPATH=$(echo "$RESULT" | cut -d'|' -f3)
if [[ -f "$RUNNER" && -d "$PREFIX" && -d "$GAMEPATH" ]]; then
echo "OK!"
echo "Found FF9 at $GAMEPATH!"
IS_HEROIC=true
else
echo -e "\nNot found! Checking for Steam installation... "
if ! pgrep steam > /dev/null; then nohup steam &> /dev/null; fi
while ! pgrep steam > /dev/null; do sleep 1; done
sleep 5
GAMEPATH=$(LIBRARY=$(getSteamLibrary 377840) && [ -n "$LIBRARY" ] && echo "$LIBRARY/steamapps/common/FINAL FANTASY IX/")
if [ -d "$GAMEPATH" ]; then
echo "OK!"
echo "Found FF9 at $GAMEPATH!"
IS_STEAM=true
else
echo "Error: Couldn't find a Steam or Heroic installation for FF9. Exiting."
exit 1
fi
fi
echo
echo "Downloading Memoria Installer"
downloadDependency "Albeoris/Memoria" "*linux*" MEMORIA
# curl -#SL "https://nightly.link/Albeoris/Memoria/actions/artifacts/7312023210.zip" -o "Memoria.Patcher.zip"
chmod +x "$MEMORIA"
if [[ ! -z "$GAMEPATH" ]]; then
./"$MEMORIA" "$GAMEPATH"
else
echo "Couldn't find a Steam or Heroic installation for FF9. Please enter the full path to the game's installation folder: "
read -r GAMEPATH
if [[ ! -d "$GAMEPATH" ]]; then
echo Not a valid directory! Exiting.
exit 1
fi
fi
sleep 5
if [ -f "$MEMORIA" ]; then
echo "Copying patcher to game directory to bypass false update prompt on first launch"
cp "$MEMORIA" "$GAMEPATH/Memoria.Patcher.exe"
echo "Cleaning up installer: $MEMORIA"
rm "$MEMORIA"
else
echo "Installer already removed: $MEMORIA"
touch "$GAMEPATH/Memoria.Patcher.exe" # Create dummy file to bypass false update prompt on first launch
fi
echo "Installation complete."
@zephyroths
Copy link
Copy Markdown

if your steam is a flatpak package you need to change the following lines:
${HOME}/.steam/root/steamapps/libraryfolders.vdf to "${HOME}/.steam/data/Steam/steamapps/libraryfolders.vdf"
$HOME/.steam/steam/steamapps/libraryfolders.vdf to $HOME/.steam/data/Steam/steamapps/libraryfolders.vdf
$HOME/.steam/steam/config/libraryfolders.vdf to $HOME/.steam/data/Steam/config/libraryfolders.vdf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment