Repository navigation
Building
-
macOS on Apple Silicon (macOS 15 or newer), or Linux with Nix (
shell.nix; Linux is built in CI but not played on). -
macOS: Xcode Command Line Tools and Homebrew:
brew install bash pkgconf glslang nasm cmake ninja spirv-tools clang-format
FSR 4.1.1 on Metal also needs Xcode with its Metal Toolchain (
xcodebuild -downloadComponent MetalToolchain), even whenxcode-selectpoints at the Command Line Tools. Without it, or withoutspirv-toolsorclang-format(DXC needs it), the build skips FSR 4.1.1 with a warning, and the game reports it unavailable. -
Your own dump of the game with update 1.09, prepared as in Game files.
git clone --recursive https://github.com/bloodborne-native/bloodborne-runtime.git
cd bloodborne-runtime
bash build.sh # the first run also builds deps/ (about an hour)
BB_GAME_DIR=/path/to/your/game bash run.sh-
build.shbuildsout/bb-probe, the GPU library and bbcpu (from therecomp/submodule).bash build.sh --testalso runs the native tests. -
deps/(MoltenVK, SDL3, FFmpeg, ...; for FSR 4.1.1 on Metal also DXC, the spirv-cross command and the fsr4-native-macos tree, without AMD's initializers) is built byscripts/macos/build-deps.sh. Its libraries record absolute paths: a moved or copieddeps/must be rebuilt (removedeps/macos-arm64, thenBB_ARCH=arm64 bash scripts/macos/build-deps.sh). - From a checkout, saves and caches go to
user/and settings tobbport.ini. - The macOS app (launcher, DMG, releases) is bloodborne-mac, which builds this repository.
run.sh reads its options from the environment; the launcher sets them from its settings.
| Variable | Effect |
|---|---|
BB_GAME_DIR |
The game folder |
BB_OUTPUT_RES=WxH, BB_RENDER_RES=WxH
|
Output size, and the game's render size (with BB_RENDER_RES, also set BB_DMEM_MB) |
BB_UPSCALER=fsr3|fsr411|metalfx|off, BB_UPSCALE_PRESET
|
Upscaler and preset |
BB_FSR411_DIR |
AMD's FSR 4.1.1 files: the Vulkan path's set, or for FSR 4.1.1 on Metal initializers.bin and initializers-ultraperformance.bin (tools/fsr4_metal_initializers.sh <the player's amd_fidelityfx_upscaler_dx12.dll>) |
BB_FSR4_METAL_SYNC=1, BB_FSR4_METAL_DIR
|
FSR 4.1.1 on Metal with CPU waits instead of shared events; its built files (default out/fsr4_metal) |
BB_FPS=uncap|90|60|30, BB_FPS_LIMIT
|
Frame-rate mode and limit |
BB_METAL_FRAME=1 |
The experimental Metal renderer |
BB_GFX_BACKEND=metal |
The render adapter's Metal backend (macOS; in progress): buffers made in Metal and imported into MoltenVK |
BB_RECOMP_LIB=PATH |
Load the recompiled library |
BB_LANGUAGE, BB_UI_LANGUAGE
|
The game's language (PS4 code), the menu's (en, pt-BR, ...) |
BB_MODS_DIR, BB_MODS_ENABLED=0
|
Mods folder, or no mods |
BB_PATCHES_DIR |
Third-party patches folder |
BB_FRAME_STATS=1 |
Frame statistics in the log |
BB_SKIP_GAME_CHECK=1 |
Skip the game folder check |
Switches for single features are listed where the feature is described in Architecture.
-
bash build.sh --test: the native tests (settings, the AV player's clock and queue, stable slot storage, texture upload hashing, ...). They need no game or GPU and also run in Linux CI, which is started by hand for now; it compiles the Linux build but does not check its rendering. -
cd tests && python3 -m unittest discover -p 'test_*.py': the script tests. On macOS the Linux-only cases fail (test_packaged_vulkan, the Intel tonemap check), andtest_probe.LoaderTestsfails (its images use 4 KiB segments; Macs have 16 KiB pages): known, not regressions.
Tests use English (BB_LANGUAGE=1 BB_UI_LANGUAGE=en; the test scripts set it). Run one game at
a time (pgrep -x bb-probe first). Test windows open on the screen.
-
tools/test_run.sh NAME [VAR=VALUE...]: a background run with a copy of the player's save (the real one is never written). It boots, loads the save, waits for the level (two frame-stat windows aboveLEVEL_DRAWS=200draws a frame), holds there (HOLD=45seconds) and prints the frame summary and any fault.SAVE_FROM=DIRstarts from a launcher backup instead;KEEP_SAVE=1keeps the previous test's progress. The test copy of the settings isout/test-user/bbport.ini(keepshow_fps=1andfps_size=bigthere). -
tools/test_opening_video.sh NAME: a new save in a fresh folder, through the opening video to character creation. Reports whether playback completed.VIDEO_GRAB=1(in the environment, not as an argument) saves the character creator's frame. Part of release testing. -
tools/grab.sh [--screen] NAME: saves the game's own frame as a PNG (--screenincludes the in-game menu and the counter). Pictures come from the game, never from the screen. - Test games are background-only apps (they never become the active app, so focus and Cmd+Q
behave unlike a launcher game). For a test someone plays in, pass
BB_BENCH_FOREGROUND=1. - Scripted menu keys:
BB_MENU_KEYS_FILE=$PWD/out/menu.keyswith tokens liker1 r1 down enter;touch out/menu.triggeropens or closes the menu. -
tools/mac_bench.sh: whattest_run.shruns underneath (SAMPLE=1takes a CPU sample,TRACE=1a Metal System Trace).
The game is GPU-bound on Apple Silicon, so CPU-side changes are measured in CPU time. Compare
alternating runs (A, B, A, B) at the same place with the same save and settings: FPS, frame-time
p90, game CPU (100% is one core) and the GPU thread's time per draw (GPU thread us/draw in the
log). A healthy run in the Hunter's Dream on an M3 Pro is about 58–62 FPS.
Runs back to back are not equal: the second of a pair reads about 5% more GPU-thread time per draw as the Mac warms up (three base-then-new pairs showed a 5% difference that a new-then-base pair did not, 4.42 against 4.36 us). Alternate which build goes first before calling a cost.
- Metal System Traces:
TRACE=1, read withtools/mst_summary.py,tools/mst_passes.py TRACE --complete-framesandtools/mst_shaders.py.xctraceneedsDEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer; recordings take over a minute to finalize after their time limit. - Metal API validation (object lifetimes):
MTL_DEBUG_LAYER=1 MTL_DEBUG_LAYER_ERROR_MODE=nslog, then search the log for "being destroyed while still required".
What has been measured so far: Performance.