Files
PSBBN-Definitive-English-Patch/scripts/PSBBN-Installer.sh
2025-08-14 22:43:21 +01:00

750 lines
26 KiB
Bash
Executable File

#!/usr/bin/env bash
# Set paths
version_check="2.10"
TOOLKIT_PATH="$(pwd)"
SCRIPTS_DIR="${TOOLKIT_PATH}/scripts"
ASSETS_DIR="${SCRIPTS_DIR}/assets"
HELPER_DIR="${SCRIPTS_DIR}/helper"
STORAGE_DIR="${SCRIPTS_DIR}/storage"
OPL="${STORAGE_DIR}/OPL"
LOG_FILE="${TOOLKIT_PATH}/logs/PSBBN-installer.log"
current_branch=$(git rev-parse --abbrev-ref HEAD)
if ! git remote | xargs -n1 git ls-remote --heads 2>/dev/null | grep -q "refs/heads/$current_branch$"; then
echo "Testing is over. Please delete the ${TOOLKIT_PATH} folder"
echo "and clone the main repository."
echo
read -n 1 -s -r -p "Press any key to exit..." </dev/tty
rm -rf "${TOOLKIT_PATH}/scripts"
echo
fi
serialnumber="$2"
path_arg="$3"
case "$1" in
-install)
MODE="install"
;;
-update)
MODE="update"
;;
*)
echo "Usage: $0 -install | -update"
exit 1
;;
esac
if [ "$MODE" = "install" ]; then
LINUX_PARTITIONS=("__linux.1" "__linux.4" "__linux.5" "__linux.6" "__linux.7" "__linux.8" "__linux.9" )
APA_PARTITIONS=("__contents" "__system" "__sysconf" "__common" "__.POPS" )
else
LINUX_PARTITIONS=("__linux.1" "__linux.4" "__linux.5" "__linux.7" "__linux.9" )
APA_PARTITIONS=("__system" "__sysconf" )
fi
error_msg() {
error_1="$1"
error_2="$2"
error_3="$3"
error_4="$4"
echo
echo "Error: $error_1" | tee -a "${LOG_FILE}"
[ -n "$error_2" ] && echo "$error_2" | tee -a "${LOG_FILE}"
[ -n "$error_3" ] && echo "$error_3" | tee -a "${LOG_FILE}"
[ -n "$error_4" ] && echo "$error_4" | tee -a "${LOG_FILE}"
echo
read -n 1 -s -r -p "Press any key to return to the main menu..." </dev/tty
echo
if [[ -n "$path_arg" ]]; then
cp "${LOG_FILE}" "$path_arg" > /dev/null 2>&1
fi
exit 1
}
clean_up() {
failure=0
# Build list of partitions we care about
targets=("${LINUX_PARTITIONS[@]}" "${APA_PARTITIONS[@]}")
if [ "$MODE" = "install" ]; then
targets+=("__linux.2")
fi
# Unmount if mounted
for PARTITION_NAME in "${targets[@]}"; do
MOUNT_PATH="${STORAGE_DIR}/${PARTITION_NAME}"
if mountpoint -q "$MOUNT_PATH"; then
if ! sudo umount "$MOUNT_PATH" 2>/dev/null; then
echo "Error: Failed to unmount ${PARTITION_NAME}." >> "${LOG_FILE}"
failure=1
fi
fi
done
# Force-remove any existing dmsetup maps for just our partitions
for PARTITION_NAME in "${targets[@]}"; do
map_name=$(sudo dmsetup ls | awk -v devcut="$(basename "$DEVICE")" -v part="$PARTITION_NAME" '$1 == devcut"-"part {print $1}')
if [ -n "$map_name" ]; then
if ! sudo dmsetup remove -f "$map_name" 2>/dev/null; then
echo "Error: Failed to delete mapper ${map_name}." >> "${LOG_FILE}"
failure=1
fi
fi
done
# Clean up directories and temp files
sudo rm -rf /tmp/{apa_header_checksum.bin,apa_header_full.bin,apajail_magic_number.bin,apa_index.xz,gpt_2nd.xz} >> "${LOG_FILE}" 2>&1
# Abort if any failures occurred
if [ "$failure" -ne 0 ]; then
error_msg "Cleanup error(s) occurred. Aborting."
fi
if [[ -n "$path_arg" ]]; then
cp "${LOG_FILE}" "$path_arg" > /dev/null 2>&1
fi
}
PFS_COMMANDS() {
PFS_COMMANDS=$(echo -e "$COMMANDS" | sudo "${HELPER_DIR}/PFS Shell.elf" >> "${LOG_FILE}" 2>&1)
if echo "$PFS_COMMANDS" | grep -q "Exit code is"; then
error_msg "PFS Shell returned an error. See ${LOG_FILE}"
fi
}
mapper_probe() {
DEVICE_CUT=$(basename "${DEVICE}")
# 1) Remove existing maps for this device
existing_maps=$(sudo dmsetup ls 2>/dev/null | awk -v p="^${DEVICE_CUT}-" '$1 ~ p {print $1}')
for map in $existing_maps; do
sudo dmsetup remove "$map" 2>/dev/null
done
# 2) Build keep list
keep_partitions=( "${LINUX_PARTITIONS[@]}" "${APA_PARTITIONS[@]}" )
if [ "$MODE" = "install" ]; then
keep_partitions+=("__linux.2")
fi
# 3) Get HDL Dump --dm output, split semicolons into lines
dm_output=$(sudo "${HELPER_DIR}/HDL Dump.elf" toc "${DEVICE}" --dm | tr ';' '\n')
# 4) Create each kept partition individually
while IFS= read -r line; do
for part in "${keep_partitions[@]}"; do
if [[ "$line" == "${DEVICE_CUT}-${part},"* ]]; then
echo "$line" | sudo dmsetup create --concise
break
fi
done
done <<< "$dm_output"
# 5) Export base mapper path
MAPPER="/dev/mapper/${DEVICE_CUT}-"
}
mount_cfs() {
for PARTITION_NAME in "${LINUX_PARTITIONS[@]}"; do
MOUNT_PATH="${STORAGE_DIR}/${PARTITION_NAME}"
if [ -e "${MAPPER}${PARTITION_NAME}" ]; then
if [[ "$PARTITION_NAME" = "__linux.8" || "$PARTITION_NAME" = "__linux.9" ]]; then
if ! sudo "${HELPER_DIR}/mkfs.vfat" -F 32 "${MAPPER}${PARTITION_NAME}" >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to create filesystem ${PARTITION_NAME}."
fi
else
if ! sudo "${HELPER_DIR}/mkfs.ext2" -b 4096 -I 128 -O ^large_file,^dir_index,^extent,^huge_file,^flex_bg,^has_journal,^ext_attr,^resize_inode "${MAPPER}${PARTITION_NAME}" >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to create filesystem ${PARTITION_NAME}."
fi
fi
[ -d "${MOUNT_PATH}" ] || mkdir -p "${MOUNT_PATH}"
if ! sudo mount "${MAPPER}${PARTITION_NAME}" "${MOUNT_PATH}" >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to mount ${PARTITION_NAME} partition."
fi
else
error_msg "Partition ${PARTITION_NAME} not found on disk."
fi
done
if ! sudo "${HELPER_DIR}/mkswap" "${MAPPER}__linux.2" >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to create swap filesystem."
fi
}
mount_pfs() {
for PARTITION_NAME in "${APA_PARTITIONS[@]}"; do
MOUNT_POINT="${STORAGE_DIR}/$PARTITION_NAME/"
mkdir -p "$MOUNT_POINT"
if ! sudo "${HELPER_DIR}/PFS Fuse.elf" \
-o allow_other \
--partition="$PARTITION_NAME" \
"${DEVICE}" \
"$MOUNT_POINT" >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to mount $PARTITION_NAME partition." "Check the device or filesystem and try again."
fi
done
}
apa_checksum_fix() {
sudo dd if=${DEVICE} of=/tmp/apa_header_full.bin bs=512 count=2 >> "${LOG_FILE}" 2>&1
"${HELPER_DIR}/PS2 APA Header Checksum Fixer.elf" /tmp/apa_header_full.bin | sed -n 8p | awk '{print $6}' | xxd -r -p > /tmp/apa_header_checksum.bin 2>> "${LOG_FILE}"
sudo dd if=/tmp/apa_header_checksum.bin of=${DEVICE} conv=notrunc >> "${LOG_FILE}" 2>&1
}
apajail_magic_number() {
echo ${MAGIC_NUMBER} | xxd -r -p > /tmp/apajail_magic_number.bin
sudo dd if=/tmp/apajail_magic_number.bin of=${DEVICE} bs=8 count=1 seek=28 conv=notrunc >> "${LOG_FILE}" 2>&1
}
BOOTSTRAP() {
if [ -f "${STORAGE_DIR}/bootstrap.xin" ]; then
# BOOTSTRAP METADATA:
BOOTSTRAP_ADDRESS_HEX_BE=0020
BOOTSTRAP_SIZE=$(wc -c "${STORAGE_DIR}/bootstrap.xin" | cut -d' ' -f 1)
BOOTSTRAP_SIZE_LBA=$(echo "$((${BOOTSTRAP_SIZE}/512))")
BOOTSTRAP_SIZE_LBA_HEX_BE=$(printf "%04X" ${BOOTSTRAP_SIZE_LBA} | tac -rs .. | echo "$(tr -d '\n')")
echo "${BOOTSTRAP_ADDRESS_HEX_BE}0000${BOOTSTRAP_SIZE_LBA_HEX_BE}0000" | xxd -r -p > /tmp/apa_header_boot.bin
# METADATA & BOOTSTRAP WRITING:
# 130h = 304d
sudo dd if=/tmp/apa_header_boot.bin of=${DEVICE} bs=1 seek=304 >> "${LOG_FILE}" 2>&1
# 2000h * 200h = 8192d * 512d = 4194304d = 400000h
sudo dd if=${STORAGE_DIR}/bootstrap.xin of=${DEVICE} bs=1M count=1 seek=4 conv=notrunc >> "${LOG_FILE}" 2>&1
else
error_msg "Failed to inject bootstrap."
fi
}
UNMOUNT_OPL() {
sync
if ! sudo umount -l "${OPL}" >> "${LOG_FILE}" 2>&1; then
error_msg "Failed to unmount $DEVICE"
fi
}
MOUNT_OPL() {
echo | tee -a "${LOG_FILE}"
echo "Mounting OPL partition." >> "${LOG_FILE}"
mkdir -p "${OPL}" 2>>"${LOG_FILE}" || error_msg "Failed to create ${OPL}."
sudo mount -o uid=$UID,gid=$(id -g) ${DEVICE}3 "${OPL}" >> "${LOG_FILE}" 2>&1
# Handle possibility host system's `mount` is using Fuse
if [ $? -ne 0 ] && hash mount.exfat-fuse; then
echo "Attempting to use exfat.fuse..." >> "${LOG_FILE}"
sudo mount.exfat-fuse -o uid=$UID,gid=$(id -g) ${DEVICE}3 "${OPL}" >> "${LOG_FILE}" 2>&1
fi
if [ $? -ne 0 ]; then
error_msg "Failed to mount the PS2 drive."
fi
}
HDL_TOC() {
rm -f "$hdl_output"
hdl_output=$(mktemp)
if ! sudo "${HELPER_DIR}/HDL Dump.elf" toc "$DEVICE" 2>>"${LOG_FILE}" > "$hdl_output"; then
rm -f "$hdl_output"
error_msg "Failed to extract list of partitions." "APA partition could be broken on ${DEVICE}"
fi
}
clear
mkdir -p "${TOOLKIT_PATH}/logs" >/dev/null 2>&1
echo "########################################################################################################" | tee -a "${LOG_FILE}" >/dev/null 2>&1
if [ $? -ne 0 ]; then
sudo rm -f "${LOG_FILE}"
echo "########################################################################################################" | tee -a "${LOG_FILE}" >/dev/null 2>&1
if [ $? -ne 0 ]; then
echo
echo "Error: Cannot to create log file."
read -n 1 -s -r -p "Press any key to return to the main menu..." </dev/tty
echo
exit 1
fi
fi
cd "${TOOLKIT_PATH}"
date >> "${LOG_FILE}"
echo >> "${LOG_FILE}"
echo "Tootkit path: $TOOLKIT_PATH" >> "${LOG_FILE}"
echo >> "${LOG_FILE}"
cat /etc/*-release >> "${LOG_FILE}" 2>&1
echo >> "${LOG_FILE}"
echo "Type: $MODE" >> "${LOG_FILE}"
echo "Disk Serial: $serialnumber" >> "${LOG_FILE}"
echo "Path: $path_arg" >> "${LOG_FILE}"
echo >> "${LOG_FILE}"
trap 'echo; exit 130' INT
trap clean_up EXIT
if [ "$MODE" = "install" ]; then
# Choose the PS2 storage device
while true; do
clear
cat << "EOF"
______ _________________ _ _ _____ _ _ _
| ___ \/ ___| ___ \ ___ \ \ | | |_ _| | | | | |
| |_/ /\ `--.| |_/ / |_/ / \| | | | _ __ ___| |_ __ _| | | ___ _ __
| __/ `--. \ ___ \ ___ \ . ` | | || '_ \/ __| __/ _` | | |/ _ \ '__|
| | /\__/ / |_/ / |_/ / |\ | _| || | | \__ \ || (_| | | | __/ |
\_| \____/\____/\____/\_| \_/ \___/_| |_|___/\__\__,_|_|_|\___|_|
EOF
if [[ -n "$serialnumber" ]]; then
DEVICE=$(lsblk -p -o NAME,SERIAL | awk -v sn="$serialnumber" '$2 == sn {print $1; exit}')
fi
if [[ -z "$DEVICE" ]]; then
echo | tee -a "${LOG_FILE}"
lsblk -p -o MODEL,NAME,SIZE,LABEL,MOUNTPOINT | tee -a "${LOG_FILE}"
echo | tee -a "${LOG_FILE}"
read -p "Choose your PS2 HDD from the list above (e.g., /dev/sdx): " DEVICE
fi
# Check if the device exists
if [[ -n "$DEVICE" ]] && lsblk -dp -n -o NAME | grep -q "^$DEVICE$"; then
# Check the size of the chosen device
SIZE_CHECK=$(lsblk -o NAME,SIZE -b | grep -w $(basename $DEVICE) | awk '{print $2}')
# Convert size to GB (1 GB = 1,000,000,000 bytes)
size_gb=$(echo "$SIZE_CHECK / 1000000000" | bc)
if (( size_gb < 200 )); then
error_msg "Device is $size_gb GB. Required minimum is 200 GB."
else
echo
echo "Selected drive: ${DEVICE}" | tee -a "${LOG_FILE}"
echo
echo "Are you sure you want to write to ${DEVICE}?" | tee -a "${LOG_FILE}"
read -p "This will erase all data on the drive. (yes/no): " CONFIRM
if [[ $CONFIRM == "yes" ]]; then
clear
break
else
echo "Aborted." | tee -a "${LOG_FILE}"
echo
read -n 1 -s -r -p "Press any key to return to the main menu..." </dev/tty
echo
exit 1
fi
fi
else
echo
echo "Invalid input. Please enter a valid device name (e.g., /dev/sdx)."
sleep 3
fi
done
else
clear
DEVICE=$(sudo blkid -t TYPE=exfat | grep OPL | awk -F: '{print $1}' | sed 's/[0-9]*$//')
if [[ -z "$DEVICE" ]]; then
error_msg "Unable to detect the PS2 drive. Please ensure the drive is properly connected." "If this is your first time using the installer, select 'Install PSBBN' from the main menu."
fi
echo "OPL partition found on $DEVICE" >> "${LOG_FILE}"
cat << "EOF"
______ _________________ _ _ _ _ _ _
| ___ \/ ___| ___ \ ___ \ \ | | | | | | | | | |
| |_/ /\ `--.| |_/ / |_/ / \| | | | | |_ __ __| | __ _| |_ ___ _ __
| __/ `--. \ ___ \ ___ \ . ` | | | | | '_ \ / _` |/ _` | __/ _ \ '__|
| | /\__/ / |_/ / |_/ / |\ | | |_| | |_) | (_| | (_| | || __/ |
\_| \____/\____/\____/\_| \_/ \___/| .__/ \__,_|\__,_|\__\___|_|
| |
|_|
EOF
# Find all mounted volumes associated with the device
mounted_volumes=$(lsblk -ln -o MOUNTPOINT "$DEVICE" | grep -v "^$")
# Iterate through each mounted volume and unmount it
echo "Unmounting volumes associated with $DEVICE..." >> "${LOG_FILE}"
for mount_point in $mounted_volumes; do
echo "Unmounting $mount_point..." >> "${LOG_FILE}"
if sudo umount "$mount_point"; then
echo "Successfully unmounted $mount_point." >> "${LOG_FILE}"
else
error_msg "Error" "Failed to unmount $mount_point. Please unmount manually."
fi
done
HDL_TOC
MOUNT_OPL
psbbn_version=$(head -n 1 "$OPL/version.txt" 2>/dev/null)
# Compare using sort -V
if [ "$(printf '%s\n' "$psbbn_version" "$version_check" | sort -V | head -n1)" != "$version_check" ]; then
UNMOUNT_OPL
error_msg "The installed PSBBN Definitive Patch is older than version $version_check and cannot be updated directly." "Please select 'Install PSBBN' from the main menu to perform a full installation."
fi
UNMOUNT_OPL
fi
# URL of the webpage
URL="https://archive.org/download/psbbn-definitive-patch-v3"
echo | tee -a "${LOG_FILE}"
echo -n "Checking for latest version of the PSBBN Definitive Patch..." | tee -a "${LOG_FILE}"
# Download the HTML of the page
HTML_FILE=$(mktemp)
timeout 20 wget -O "$HTML_FILE" "$URL" -o - 2>&1 >> "${LOG_FILE}"
# Extract .gz filenames from the HTML
COMBINED_LIST=$(grep -oP 'psbbn-definitive-patch-v[0-9]+\.[0-9]+\.tar.gz' "$HTML_FILE")
# Extract version numbers and sort them
VERSION_LIST=$(echo "$COMBINED_LIST" | \
grep -oP 'v[0-9]+\.[0-9]+' | \
sed 's/v//' | \
sort -V)
# Determine the latest version from the sorted list
LATEST_VERSION=$(echo "$VERSION_LIST" | tail -n 1)
if [ -z "$LATEST_VERSION" ]; then
echo | tee -a "${LOG_FILE}"
echo "Could not find the latest version." | tee -a "${LOG_FILE}"
# If $LATEST_VERSION is empty, check for psbbn-definitive-patch*.gz files
PATCH_FILE=$(ls "${ASSETS_DIR}"/psbbn-definitive-patch*.tar.gz 2>/dev/null)
if [ -n "$PATCH_FILE" ]; then
# If patch file exists, set LATEST_FILE to the patch file name
LATEST_VERSION=$(echo "$PATCH_FILE" | sed -E 's/.*-v([0-9.]+)\.tar.gz/\1/')
LATEST_FILE=$(basename "$PATCH_FILE")
echo | tee -a "${LOG_FILE}"
echo "Found local file: ${LATEST_FILE}" | tee -a "${LOG_FILE}"
else
rm -f "$HTML_FILE"
error_msg "Failed to download PSBBN patch file. Aborting."
fi
else
# Set the default latest file based on remote version
LATEST_FILE="psbbn-definitive-patch-v${LATEST_VERSION}.tar.gz"
echo | tee -a "${LOG_FILE}"
echo "Latest version of PSBBN Definitive English patch is v${LATEST_VERSION}" | tee -a "${LOG_FILE}"
# Check if any local file is newer than the remote version
PATCH_FILE=$(ls "${ASSETS_DIR}"/psbbn-definitive-patch*.tar.gz 2>/dev/null | sort -V | tail -n1)
if [ -n "$PATCH_FILE" ]; then
LOCAL_VERSION=$(echo "$PATCH_FILE" | sed -E 's/.*-v([0-9.]+)\.tar.gz/\1/')
# Compare local vs remote version
if [ "$(printf '%s\n' "$LATEST_VERSION" "$LOCAL_VERSION" | sort -V | tail -n1)" != "$LATEST_VERSION" ]; then
LATEST_VERSION="$LOCAL_VERSION"
LATEST_FILE=$(basename "$PATCH_FILE")
echo "Newer local file found: ${LATEST_FILE}" | tee -a "${LOG_FILE}"
fi
fi
fi
echo "Latest version: $LATEST_VERSION" | tee -a "${LOG_FILE}"
if [ "$MODE" = "update" ]; then
echo "Current version: $psbbn_version"
if [ "$(printf '%s\n' "$LATEST_VERSION" "$psbbn_version" | sort -V | tail -n1)" = "$psbbn_version" ]; then
echo
echo "You are already running the latest version. No need to update." | tee -a "${LOG_FILE}"
echo
read -n 1 -s -r -p "Press any key to return to the main menu..." </dev/tty
echo
exit 0
fi
fi
# Check if the latest file exists in ${ASSETS_DIR}
if [[ -f "${ASSETS_DIR}/${LATEST_FILE}" && ! -f "${ASSETS_DIR}/${LATEST_FILE}.st" ]]; then
echo "File ${LATEST_FILE} exists in ${ASSETS_DIR}." | tee -a "${LOG_FILE}"
echo "Skipping download." | tee -a "${LOG_FILE}"
else
# Check for and delete older files
for file in "${ASSETS_DIR}"/psbbn-definitive-patch*.tar.gz; do
if [[ -f "$file" && "$(basename "$file")" != "$LATEST_FILE" ]]; then
echo "Deleting old file: $file" | tee -a "${LOG_FILE}"
rm -f "$file"
fi
done
# Construct the full URL for the .gz file and download it
ZIP_URL="$URL/$LATEST_FILE"
echo "Downloading ${LATEST_FILE}..." | tee -a "${LOG_FILE}"
axel -n 8 -a "$ZIP_URL" -o "${ASSETS_DIR}"
# Check if the file was downloaded successfully
if [[ -f "${ASSETS_DIR}/${LATEST_FILE}" && ! -f "${ASSETS_DIR}/${LATEST_FILE}.st" ]]; then
echo "Download completed: ${LATEST_FILE}" | tee -a "${LOG_FILE}"
else
error_msg "Download failed for ${LATEST_FILE}. Please check your internet connection and try again."
fi
fi
# Clean up
rm -f "$HTML_FILE"
PSBBN_PATCH="${ASSETS_DIR}/${LATEST_FILE}"
clean_up
if [ "$MODE" = "install" ]; then
echo | tee -a "${LOG_FILE}"
echo "Initialising drive..." | tee -a "${LOG_FILE}"
COMMANDS="device ${DEVICE}\n"
COMMANDS+="initialize yes\n"
COMMANDS+="mkpart __linux.1 512M EXT2\n"
COMMANDS+="mkpart __linux.2 128M EXT2SWAP\n"
COMMANDS+="mkpart __linux.4 512M EXT2\n"
COMMANDS+="mkpart __linux.5 512M EXT2\n"
COMMANDS+="mkpart __linux.6 128M EXT2\n"
COMMANDS+="mkpart __linux.7 256M EXT2\n"
COMMANDS+="mkpart __linux.9 3072M EXT2\n"
COMMANDS+="exit"
PFS_COMMANDS
# Retreive avaliable space
output=$(sudo "${HELPER_DIR}"/HDL\ Dump.elf toc ${DEVICE} 2>&1)
# Extract the "used" value, remove "MB" and any commas
used=$(echo "$output" | awk '/used:/ {print $6}' | sed 's/,//; s/MB//')
capacity=129960
# Calculate available space (capacity - used)
available=$((capacity - used - 6400 - 128))
free_space=$((available / 1024))
max_music=$(((available - 2048) / 1024))
# Prompt user for partition size for music and POPS, validate input, and keep asking until valid input is provided
while true; do
echo | tee -a "${LOG_FILE}"
echo "Partitioning the first 128 GB of the drive:"
echo
echo "Available: $free_space GB" | tee -a "${LOG_FILE}"
echo
echo "What size would you like the \"Music\" partition to be?"
echo "Minimum 1 GB, maximum $max_music GB"
echo
read -p "Enter partition size (in GB): " music_gb
if [[ ! "$music_gb" =~ ^[0-9]+$ ]]; then
echo
echo "Invalid input. Please enter a valid number."
sleep 3
continue
fi
if (( music_gb < 1 || music_gb > max_music )); then
echo
echo "Invalid size. Please enter a value between 1 and $max_music GB."
sleep 3
continue
fi
remaining_gb=$((free_space - music_gb -1))
echo
echo "What size would you like the \"contents\" partition to be?"
echo "This partition is used to store movies and photos."
echo "Minimum 1 GB, maximum $remaining_gb GB"
echo
read -p "Enter partition size (in GB): " contents_gb
if [[ ! "$contents_gb" =~ ^[0-9]+$ ]]; then
echo
echo "Invalid input. Please enter a valid number."
sleep 3
continue
fi
if (( contents_gb < 1 || contents_gb > remaining_gb )); then
echo
echo "Invalid size. Please enter a value between 1 and $remaining_gb GB."
sleep 3
continue
fi
remaining_gb=$((free_space - music_gb - contents_gb))
echo
echo "What size would you like the \"POPS\" partition to be?"
echo "This partition is used to store PS1 games."
echo "Minimum 1 GB, maximum $remaining_gb GB"
echo
read -p "Enter partition size (in GB): " pops_gb
if [[ ! "$pops_gb" =~ ^[0-9]+$ ]]; then
echo
echo "Invalid input. Please enter a valid number."
sleep 3
continue
fi
if (( pops_gb < 1 || pops_gb > remaining_gb )); then
echo
echo "Invalid size. Please enter a value between 1 and $remaining_gb GB."
sleep 3
continue
fi
allocated_gb=$((music_gb + pops_gb + contents_gb))
unallocated_gb=$((free_space - allocated_gb))
echo
echo "The following partitions will be created:"
echo "- Music partition: $music_gb GB"
echo "- Contents partition: $contents_gb GB"
echo "- POPS partition: $pops_gb GB"
echo "- Remaining space: $unallocated_gb GB"
echo
read -p "Do you wish to proceed? (y/n): " confirm
if [[ "$confirm" =~ ^[Yy]$ ]]; then
music_partition=$((music_gb * 1024))
pops_partition=$((pops_gb * 1024))
contents_partition=$((contents_gb * 1024))
break
fi
done
echo >> "${LOG_FILE}"
echo "Music partition size: $music_partition" >> "${LOG_FILE}"
echo "POPS partition size: $pops_partition" >> "${LOG_FILE}"
echo "Contents partition size: $contents_partition" >> "${LOG_FILE}"
COMMANDS="device ${DEVICE}\n"
COMMANDS+="mkpart __linux.8 ${music_partition}M EXT2\n"
COMMANDS+="mkpart __.POPS ${pops_partition}M PFS\n"
COMMANDS+="mkpart __contents ${contents_partition}M PFS\n"
COMMANDS+="mkpart +OPL 128M PFS\n"
COMMANDS+="exit"
echo | tee -a "${LOG_FILE}"
echo -n "Creating partitions..." | tee -a "${LOG_FILE}"
echo
PFS_COMMANDS
fi
echo -n "Installing PSBBN..." | tee -a "${LOG_FILE}"
mapper_probe
mount_cfs
mount_pfs
if [ "$MODE" = "install" ]; then
sudo mkdir -p "${STORAGE_DIR}/__linux.8/MusicCh/contents"
sudo mkdir -p "${STORAGE_DIR}/__common"/{POPS,"Your Saves"}
sudo cp "${ASSETS_DIR}/POPStarter/eng"/{IGR_BG.TM2,IGR_NO.TM2,IGR_YES.TM2} "${STORAGE_DIR}/__common/POPS/"
fi
if ! sudo tar zxvpf "${PSBBN_PATCH}" --no-same-owner -C "${STORAGE_DIR}/" >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to extract files. Install Failed."
fi
BOOTSTRAP
clean_up
if [ "$MODE" = "install" ]; then
################################### APA-Jail code by Berion ###################################
echo | tee -a "${LOG_FILE}"
echo -n "Running APA-Jail..." | tee -a "${LOG_FILE}"
# Signature injection (type A2):
MAGIC_NUMBER="4150414A2D413200"
apajail_magic_number
# Setting up MBR:
{
echo -e ",128GiB,17\n,32MiB,17\n,,07" | sudo sfdisk ${DEVICE}
sudo partprobe ${DEVICE}
if [ "$(echo ${DEVICE} | grep -o /dev/loop)" = "/dev/loop" ]; then
sudo mkfs.ext2 -L "RECOVERY" ${DEVICE}p2
sudo "${HELPER_DIR}/mkfs.exfat" -c 32K -L "OPL" ${DEVICE}p3
else
sleep 4
sudo mkfs.ext2 -L "RECOVERY" ${DEVICE}2
sudo "${HELPER_DIR}/mkfs.exfat" -c 32K -L "OPL" ${DEVICE}3
fi
} >> "${LOG_FILE}" 2>&1
PARTITION_NUMBER=3
# Finalising recovery:
if [ ! -d "${STORAGE_DIR}/recovery" ]; then
mkdir -p "${STORAGE_DIR}/recovery" 2>> "${LOG_FILE}"
fi
if [ "$(echo ${DEVICE} | grep -o /dev/loop)" = "/dev/loop" ]; then
sudo mount ${DEVICE}p2 "${STORAGE_DIR}/recovery" 2>> "${LOG_FILE}"
else
sudo mount ${DEVICE}2 "${STORAGE_DIR}/recovery" 2>> "${LOG_FILE}"
fi
sudo dd if=${DEVICE} bs=128M count=1 status=noxfer 2>> "${LOG_FILE}" | xz -z > /tmp/apa_index.xz 2>> "${LOG_FILE}"
sudo cp /tmp/apa_index.xz "${STORAGE_DIR}/recovery" 2>> "${LOG_FILE}"
LBA_MAX=$(sudo blockdev --getsize ${DEVICE})
LBA_GPT_BUP=$(echo $(($LBA_MAX-33)))
sudo dd if=${DEVICE} skip=${LBA_GPT_BUP} bs=512 count=33 status=noxfer 2>> "${LOG_FILE}" | xz -z > /tmp/gpt_2nd.xz 2>> "${LOG_FILE}"
sudo cp /tmp/gpt_2nd.xz "${STORAGE_DIR}/recovery" 2>> "${LOG_FILE}"
sync 2>> "${LOG_FILE}"
sudo umount -l "${STORAGE_DIR}/recovery" 2>> "${LOG_FILE}"
###############################################################################################
fi
apa_checksum_fix
# Run the command and capture output
echo >> "${LOG_FILE}"
TOC_OUTPUT=$(sudo "${HELPER_DIR}/HDL Dump.elf" toc "${DEVICE}")
STATUS=$?
if [ $STATUS -ne 0 ]; then
error_msg "APA partition is broken on ${DEVICE}. Install failed."
fi
if echo "${TOC_OUTPUT}" | grep -Eq '\b(__linux\.(1|4|5|6|7|8|9)|__contents|__system|__sysconf|__.POPS|__common)\b'; then
echo "All partitions exist." >> "${LOG_FILE}"
else
error_msg "Error" "Some partitions are missing on ${DEVICE}. See log for details."
fi
MOUNT_OPL
if [ "$MODE" = "install" ]; then
if ! mkdir -p "${OPL}"/{APPS,ART,CFG,CHT,LNG,THM,VMC,CD,DVD,bbnl} >>"${LOG_FILE}" 2>&1; then
error_msg "Failed to create OPL folders."
fi
fi
echo "$LATEST_VERSION" > "${OPL}/version.txt"
echo "eng" >> "${OPL}/version.txt"
UNMOUNT_OPL
echo >> "${LOG_FILE}"
echo "${TOC_OUTPUT}" >> "${LOG_FILE}"
echo >> "${LOG_FILE}"
lsblk -p -o MODEL,NAME,SIZE,LABEL,MOUNTPOINT >> "${LOG_FILE}"
echo | tee -a "${LOG_FILE}"
if [ "$MODE" = "install" ]; then
echo "PSBBN successfully installed." | tee -a "${LOG_FILE}"
else
echo "PSBBN successfully updated." | tee -a "${LOG_FILE}"
echo
echo "Now connect the drive to your PS2 console and boot into PSBBN to finish the installation."
fi
echo
read -n 1 -s -r -p "Press any key to return to the main menu..." </dev/tty
echo