mirror of
https://github.com/ayozetr/bloodborne_linux.git
synced 2026-11-07 09:46:04 -10:00
The game's code was built for the PS4's CPU and has 987 movbe. AMD's FX processors of the Piledriver generation have every other instruction the game uses but not this one, so the game stopped with SIGILL (exit code 132) at the first one, while reading a file header (#39). The SIGILL handler now decodes the movbe at the faulting address, does the load or store with its bytes swapped and resumes after it. On a processor with MOVBE this never runs. The CPU check no longer refuses to start without MOVBE and says in the log that the port runs them; the log also counts them every 10 s (a few thousand a second while loading, about ten a second while playing). BB_MOVBE_TRAP=file turns the movbe listed by tools/movbe_sites.py into ud2, so the emulation can be tested on any processor. tests/test_movbe.c checks the forms the game uses.
153 lines
9.7 KiB
Bash
153 lines
9.7 KiB
Bash
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
cd -- "$(dirname -- "$0")"
|
|
mkdir -p out
|
|
if [[ -z ${CC:-} ]]; then
|
|
CC=$(command -v cc || command -v gcc || true)
|
|
if [[ -z $CC ]]; then
|
|
for candidate in /nix/store/*-gcc-wrapper-*/bin/gcc; do
|
|
if [[ -x $candidate ]]; then CC=$candidate; break; fi
|
|
done
|
|
fi
|
|
fi
|
|
if [[ -z ${CC:-} ]]; then echo 'Install GCC/Clang or set CC.' >&2; exit 1; fi
|
|
# Dependencies come from pkg-config (Vulkan loader/headers, SDL3). On NixOS the
|
|
# environment is provided by shell.nix; re-enter it automatically if needed.
|
|
if ! { command -v pkg-config >/dev/null && pkg-config --exists vulkan sdl3 && command -v cmake >/dev/null && command -v ninja >/dev/null; }; then
|
|
if [[ -z ${BB_IN_NIX_SHELL:-} ]] && command -v nix-shell >/dev/null; then
|
|
exec env BB_IN_NIX_SHELL=1 nix-shell shell.nix --run "bash build.sh $*"
|
|
fi
|
|
echo 'Need pkg-config with vulkan and sdl3, cmake and ninja (see shell.nix).' >&2; exit 1
|
|
fi
|
|
read -r -a includes <<< "$(pkg-config --cflags vulkan sdl3)"
|
|
read -r -a libraries <<< "$(pkg-config --libs vulkan sdl3)"
|
|
# GPU library (shadPS4 video core + drivers), built by CMake into out/gpu/libbbgpu.so.
|
|
# BB_PGO: generate (instrumented build that writes pgo/ while the game runs), use, off.
|
|
# Default: use the profile in pgo/ when there is one. BB_LTO=OFF disables link-time optimization.
|
|
pgo=${BB_PGO:-}
|
|
if [[ -z $pgo ]]; then
|
|
if [[ -n $(find pgo -name '*.gcda' -print -quit 2>/dev/null) ]]; then pgo=use; else pgo=off; fi
|
|
fi
|
|
# A profile only applies when its files are named as this build names them (relative to out/gpu,
|
|
# -fprofile-prefix-path): one recorded elsewhere matched nothing and PGO was silently off.
|
|
if [[ $pgo == use && -z $(find pgo -name 'CMakeFiles#bbgpu.dir#*.gcda' -print -quit 2>/dev/null) ]]; then
|
|
echo 'PGO: the profile in pgo/ is from another build layout (rebuild it: BB_PGO=generate); built without it' >&2
|
|
pgo=off
|
|
fi
|
|
mkdir -p pgo
|
|
# Submodules (git clone --recursive, or: git submodule update --init) and this port's changes
|
|
# to FSR-Vulkan (gpu/patches/fsr-vulkan), applied to its working tree once.
|
|
if [[ ! -f gpu/third_party/fsr-vulkan/CMakeLists.txt || ! -f gpu/third_party/imgui/imgui.h ]]; then
|
|
git submodule update --init --recursive
|
|
fi
|
|
# Issue #124: a checkout updated from an earlier version keeps that version's patch applied, and
|
|
# the new one applies neither way ("patch does not apply"): the submodule's tree holds nothing but
|
|
# these patches, so it is reset and they are applied again.
|
|
fsr_patches_apply() {
|
|
for patch in gpu/patches/fsr-vulkan/*.patch; do
|
|
if ! git -C gpu/third_party/fsr-vulkan apply --reverse --check "$PWD/$patch" 2>/dev/null; then
|
|
git -C gpu/third_party/fsr-vulkan apply "$@" "$PWD/$patch" || return 1
|
|
fi
|
|
done
|
|
}
|
|
if ! fsr_patches_apply --check 2>/dev/null; then
|
|
echo 'FSR-Vulkan: an earlier version of the port changed it; resetting it and patching again'
|
|
git -C gpu/third_party/fsr-vulkan checkout -- .
|
|
fi
|
|
fsr_patches_apply
|
|
cmake -S gpu -B out/gpu -G Ninja -DCMAKE_BUILD_TYPE=RelWithDebInfo -DBB_PGO="$pgo" \
|
|
-DBB_LTO="${BB_LTO:-ON}" -DBB_PGO_DIR="$PWD/pgo" > out/gpu-cmake.log
|
|
grep '^-- Online module' out/gpu-cmake.log || true
|
|
echo "GPU library: PGO $pgo, LTO ${BB_LTO:-ON}"
|
|
# A failed GPU build must stop here: an older libbbgpu.so would otherwise be used silently.
|
|
if ! ninja -C out/gpu bbgpu $(grep -q "^build bbnet20:" out/gpu/build.ninja && echo bbnet20) > out/gpu-build.log 2>&1; then
|
|
grep -v '^\[' out/gpu-build.log | tail -40 >&2
|
|
echo 'GPU library build failed (full log: out/gpu-build.log)' >&2; exit 1
|
|
fi
|
|
# Optional DLSS (NVIDIA RTX): DLSS_SDK_ROOT=<github.com/NVIDIA/DLSS checkout> builds the bridge
|
|
# (gpu/dlss_bridge, the only code using NVIDIA's SDK) and puts it next to bb-probe with NVIDIA's
|
|
# libnvidia-ngx-dlss.so (Super Resolution) and libnvidia-ngx-dlssg.so (Frame Generation, GeForce
|
|
# RTX 40 and newer; SDK 310.7 or newer has it). Without them the DLSS upscaler and DLSS Frame
|
|
# Generation are listed as unavailable.
|
|
if [[ -n ${DLSS_SDK_ROOT:-} ]]; then
|
|
cmake -S gpu/dlss_bridge -B out/dlss-bridge -G Ninja -DCMAKE_BUILD_TYPE=Release \
|
|
-DDLSS_SDK_ROOT="$DLSS_SDK_ROOT" >/dev/null
|
|
ninja -C out/dlss-bridge >/dev/null
|
|
rm -f out/libnvidia-ngx-dlss.so.* out/libnvidia-ngx-dlssg.so.*
|
|
cp out/dlss-bridge/libbbport_dlss.so "$DLSS_SDK_ROOT"/lib/Linux_x86_64/rel/libnvidia-ngx-dlss.so.* out/
|
|
if ls "$DLSS_SDK_ROOT"/lib/Linux_x86_64/rel/libnvidia-ngx-dlssg.so.* >/dev/null 2>&1; then
|
|
cp "$DLSS_SDK_ROOT"/lib/Linux_x86_64/rel/libnvidia-ngx-dlssg.so.* out/
|
|
echo "DLSS Frame Generation library: $(ls out/libnvidia-ngx-dlssg.so.*)"
|
|
else
|
|
echo "DLSS Frame Generation library not in this SDK (lib/Linux_x86_64/rel/libnvidia-ngx-dlssg.so.*): DLSS Super Resolution only"
|
|
fi
|
|
cp "$DLSS_SDK_ROOT/LICENSE.txt" out/NVIDIA-DLSS-LICENSE.txt
|
|
echo "DLSS bridge: out/libbbport_dlss.so"
|
|
fi
|
|
# Installing from PS4 packages (launcher: Install from PKG, scripts/pkg_install.py): pkgextract
|
|
# (github.com/paulomanrique/ps4-pkg-extractor, Unlicense) at a reviewed revision, with its
|
|
# Cargo.lock. Needs cargo; without it the launcher asks for a game folder only.
|
|
pkgextract_rev=f430ce1634fc7953834b545a3946bfbd5fa216fa
|
|
if [[ ! -x out/pkgextract/bin/pkgextract ]] && command -v cargo >/dev/null; then
|
|
if cargo install --quiet --locked --root out/pkgextract \
|
|
--git https://github.com/paulomanrique/ps4-pkg-extractor --rev "$pkgextract_rev" pkgextract \
|
|
>out/pkgextract-build.log 2>&1; then
|
|
echo 'PKG extractor: out/pkgextract/bin/pkgextract'
|
|
else
|
|
echo 'pkgextract build failed (out/pkgextract-build.log): Install from PKG is not offered' >&2
|
|
fi
|
|
fi
|
|
# $ORIGIN/gpu: packaged copies keep the library next to the binary without patching it.
|
|
gpu=(-Lout/gpu -lbbgpu -Wl,-rpath,'$ORIGIN/gpu' -Wl,-rpath,"$PWD/out/gpu" -rdynamic)
|
|
runtime=(src/runtime*.c)
|
|
# Third-party decoders: compiled once, without this project's -Werror policy.
|
|
atrac9=(third_party/LibAtrac9/C/src/*.c)
|
|
if [[ ! -f out/libatrac9.a || -n $(find third_party/LibAtrac9/C/src -newer out/libatrac9.a -name '*.c') ]]; then
|
|
rm -rf out/atrac9 && mkdir -p out/atrac9
|
|
for source in "${atrac9[@]}"; do "$CC" -std=c99 -O2 -g -w -c "$source" -o "out/atrac9/$(basename "${source%.c}").o"; done
|
|
ar rcs out/libatrac9.a out/atrac9/*.o
|
|
fi
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -no-pie "${includes[@]}" -I. -Isrc src/probe.c "${runtime[@]}" src/vulkan_smoke.c out/libatrac9.a -lm "${gpu[@]}" "${libraries[@]}" -o out/bb-probe
|
|
echo "Built $PWD/out/bb-probe"
|
|
# GPU check for run.sh (live_resolution=auto) and the launcher's gamepad list (--gamepads).
|
|
"$CC" -std=c11 -O2 -Wall -Wextra -Werror "${includes[@]}" tools/gpu_capabilities.c "${libraries[@]}" -o out/bb-gpu-capabilities
|
|
if [[ ${1:-} == --test ]]; then
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread "${includes[@]}" -I. -Isrc tests/test_pad.c "${libraries[@]}" -lm -o out/pad-test
|
|
out/pad-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread "${includes[@]}" -I. -Isrc tests/test_pad_atlas.c "${libraries[@]}" -lm -o out/pad-atlas-test
|
|
out/pad-atlas-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -I. -Isrc tests/test_runtime.c "${runtime[@]}" out/libatrac9.a -lm "${gpu[@]}" "${libraries[@]}" -o out/runtime-test
|
|
out/runtime-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -Isrc tests/test_movbe.c src/runtime_movbe.c -o out/movbe-test
|
|
out/movbe-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -Isrc tests/test_file_mods.c src/runtime_remote.c -o out/file-mods-test
|
|
out/file-mods-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -I. -Isrc tests/test_sema.c "${runtime[@]}" out/libatrac9.a -lm "${gpu[@]}" "${libraries[@]}" -o out/sema-test
|
|
out/sema-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -I. -Isrc tests/test_online.c "${runtime[@]}" out/libatrac9.a -lm "${gpu[@]}" "${libraries[@]}" -o out/online-test
|
|
out/online-test
|
|
"$CC" -std=c11 -D_GNU_SOURCE -O2 -g -Wall -Wextra -Werror -I. -Isrc tests/test_content.c src/runtime_content.c -o out/content-test
|
|
out/content-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -Isrc tests/test_trophy.c src/runtime_trophy.c -o out/trophy-test
|
|
out/trophy-test out/trophy_test_tmp
|
|
# Hunter's Atlas: its guarded game-memory readers on synthetic images.
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -Isrc tests/test_map_location.c src/runtime_map.c -lm -o out/map-location-test
|
|
out/map-location-test
|
|
"$CC" -std=c11 -O2 -g -Wall -Wextra -Werror -pthread -Isrc tests/test_atlas_state.c src/runtime_atlas_state.c -lm -o out/atlas-state-test
|
|
out/atlas-state-test
|
|
# Hunter's Atlas: its tile's state machine, map styles, floor interiors, controller shortcut.
|
|
# (-Wno-misleading-indentation: Atlas's compact one-line style.) bbport (Linux fork):
|
|
# nlohmann/json from the system, as gpu/CMakeLists.txt.
|
|
atlas_cxx=(-std=c++20 -O2 -g -Wall -Wextra -Werror -Wno-misleading-indentation -Igpu/shim -Igpu/third_party/imgui "${includes[@]}")
|
|
for test in test_bbport_atlas_menu_state test_bbport_atlas_style test_bbport_atlas_interiors; do
|
|
"${CXX:-c++}" "${atlas_cxx[@]}" "tests/$test.cpp" -o "out/$test" || exit 1
|
|
(cd out && "./$test") || exit 1
|
|
done
|
|
"${CXX:-c++}" "${atlas_cxx[@]}" tests/test_map_controller.cpp gpu/shim/bbport_map_controller.cpp "${libraries[@]}" -o out/map-controller-test
|
|
out/map-controller-test
|
|
"${CXX:-c++}" "${atlas_cxx[@]}" tests/test_atlas_features.cpp gpu/shim/bbport_map_features.cpp "${libraries[@]}" -o out/atlas-features-test
|
|
rm -rf out/atlas-features && out/atlas-features-test out/atlas-features
|
|
"${CXX:-c++}" "${atlas_cxx[@]}" tests/test_atlas_i18n.cpp -o out/atlas-i18n-test
|
|
out/atlas-i18n-test
|
|
fi
|