Compare commits

...
Author SHA1 Message Date
ayozetr 97a60dd497 0.51-linux.2, and co-op on your own server tested with two players
The launcher's version for the About page's updates. docs/SERVER.md and the README say that a
private server has been tested with a Linux and a Windows player: summons, a boss fight together
and summoning again after the helper died.
2026-10-11 16:51:45 +01:00
0xCydral a3a8a3af6e fix(vulkan): include vulkan.hpp with NDEBUG so the dispatcher layout matches
vulkan.hpp adds two fields to DispatchLoaderBase when NDEBUG is undefined, which moves every
function pointer in vk::detail::DispatchLoaderDynamic by 16 bytes. libbbgpu is built with NDEBUG
while the renderer tests build with -UNDEBUG so their asserts run, so the two sides disagreed on
the layout. The linker keeps one inline copy of DispatchLoaderDynamic::init(Instance): the test
translation unit's copy read vkGetInstanceProcAddr at offset 88 while CreateInstance had stored it
at offset 72, and Instance construction called a null pointer (exit 139 on Windows).

vk_common.h now defines NDEBUG around the vulkan.hpp include and restores assert() afterwards,
so every translation unit sees the same layout while test asserts stay active.

(cherry picked from commit 03b383b34ccb74085d74baa1e3b87ca0b50013aa)
2026-10-11 16:50:59 +01:00
0xCydral f1091cc0b1 fix(gpu): keep the camera vector where an object vector strays far from it
Object motion history that was not the object's gave still geometry huge
vectors. At one moment of the Hunter's Dream test route, bushes behind the
workshop moved 100-650 px a frame while the camera vectors around them were
right, and FSR and frame generation smeared them. The motion merge now keeps
the camera vector when the object vector differs from it by more than 5% of
the render width (at least 32 px; 85 px at 1706x960).

Measured on 24 frames at the same moment: object vectors over 100 px went
from 2.8% of the picture on the worst frames of two runs to none. The camera
motion test gains two cases, a far object vector that is rejected and a 30 px
one that is kept; that test does not run on Windows yet.

(cherry picked from commit a12911460872b37aba2bff4895903ad20aabf1e2)
2026-10-11 16:50:59 +01:00
0xCydral c496667284 feat(log): a performance line every 30 seconds in normal play
Players' last_run.log carried no frame rate, so a report of low FPS or stutter came with nothing
to measure. Without BB_FRAME_STATS the game now prints one line per 30 seconds: game frames per
second, the 1% low, the worst frame and the shader/pipeline compiles of the window, for example
"Perf: 68.0 FPS over 30 s, 1% low 62.8 FPS, worst frame 22.1 ms, 0 shader/pipeline compiles".

(cherry picked from commit 6c73bf375ea55972fd19bb5dcc254a92ab57ee54)
2026-10-11 16:50:59 +01:00
0xCydral a8b7a8eaa1 fix(gpu): keep the default indirect guard limit when BB_INDIRECT_GUARD_MAX is not a positive number
An unparsable value gave strtoul 0, so the shader skipped every indirect dispatch without a word. A value that is not a number from 1 to 4294967295 now keeps the default and prints one warning line.

(cherry picked from commit 62177377cf6c4a390d95d61b804505b077e7648c)
2026-10-11 16:50:59 +01:00
0xCydral 4d934b7529 fix(run.sh): give an explicit render size above 1080p the larger direct memory
run.sh raised BB_DMEM_MB to 9152 MiB only on the scaled path. An explicit BB_RENDER_RES skips that path, but patches.py still grows the graphics heap above 1080p, so the game asked for more memory than it had and stopped at start (exit 139). run.sh now does what run.py does since e5276cf: a WxH size above 1920x1080 by pixel count gets 9152 MiB unless BB_DMEM_MB is already set.

(cherry picked from commit 674b72e650f990dce906bc43446d024ab7109520)
2026-10-11 16:50:59 +01:00
0xCydral 442c2b66bd fix(gpu): resync the graphics command decoder at an invalid PM4 header
A cut-short SET_SH_REG leaves the next packets inside its body, and the
decoder then hit UNREACHABLE (Unimplemented PM4 type 0) at area loads. On
that path only, decoding now resumes at the next dword that can start a
type 3 packet, so the rest of the buffer and its fences still run. Each
resync logs the header dword and its offset; the buffer report stays
limited to the first 8.

From GoncaloLobo0/bloodborne_pc_win a334d26 and 9dc909d (adapted: crash path
only, no look-ahead on valid register packets)

(cherry picked from commit e0b464db61362d5c8b966ec645c592cf0a680667)
2026-10-11 16:50:59 +01:00
0xCydral d7a42fde94 fix(motion): object vectors for 16-64 KiB bone palettes; unknown SnormNz format is not fatal
Palettes of whole bones between 16 and 64 KiB (24576, 49152 bytes: the
large beasts in Central Yharnam) are now LargeSkeleton: gated like small
skeletons (history only while the palette changes). BB_MOTION_LARGE=0
restores the old rule (camera vectors only).

MapNumberConversion returns NumberConversion::None for a data format with
no SnormNz mapping instead of hitting UNREACHABLE (seen with data format 45,
a stale or unused descriptor).

From bmy/bbport-mac 80898cf and 5cf5684 (gpu part only)

(cherry picked from commit 4ff6b6292df844129332d75c6a1eb56eda14232b)
2026-10-11 16:50:59 +01:00
0xCydral d0318b1ab5 fix(upscaler): UI mask draws write the UI's output-size stencil
Scaleform masks are drawn with color writes off, so they reached the UI
composition without a color target and stayed in the game-size depth. The
next UI draw switched to the output-size UI depth, whose stencil
PrepareUiDepth clears, and the mask was gone: images cut out through a mask
(the loading screen's item picture) vanished at output sizes other than
1080p.

The frame generation HUD-less capture is unaffected: it runs in the
!Scaled() path before ui_phase, and the new branch only applies in ui_phase.

From bmy/bbport-mac e4f7d33

(cherry picked from commit 55b4a0d7247ec05dafc0d40643a2a146869c9531)
2026-10-11 16:50:59 +01:00
0xCydral 1bc4f37504 fix(texture-cache): hash the same guest range at marking and refresh
MarkAsMaybeDirty hashed the whole image but RefreshImage only its first 8x8
pixels, so the two never matched and stale guest memory replaced
GPU-written small images (black character preview, missing loading-screen
item picture). Both now use MaybeDirtyHash, and every upload records its
mip hash so an unchanged guest copy is not re-uploaded over GPU contents.

From yumlevi/bloodborne_pc 43fcf95

(cherry picked from commit 0d2dfd2f4ba3a13d5bee415769f5f0ff4f58fb2e)
2026-10-11 16:50:59 +01:00
0xCydral 44a6b7c3ce fix(shader): ReadUdReg on a null user-data table returns an empty sharp
An unbound descriptor table dereferenced a near-null pointer (access
violation at 0x8 on map load). Return a zeroed value so the existing
empty-sharp handling runs.

From Mrsuss60/bloodborne_pc_windows_port 8d8ac28 (info.h hunk only)

(cherry picked from commit 5e4513bad8b952bea95f6df76d94c97d5e827de8)
2026-10-11 16:50:59 +01:00
0xCydral efdf7b176e fix(runtime): split flexible mappings keep their own pool offset
split_at moved the offset only for direct memory, so the right piece of a
split flexible mapping kept the left piece's. Unmapping it then freed and
zeroed the left piece's pages (still mapped) and leaked its own; read/write
backing used the wrong pages too.

From bmy/bbport-mac 9ffc78d

(cherry picked from commit 389a1e5c3573460f73f96f255f5fbf7da43c981c)
2026-10-11 16:50:59 +01:00
ayozetr 4f7df3de5c Trophies: a notice in the game and a Trophies page
The game's trophies come from the player's own dump: scripts/trophies.py reads
sce_sys/trophy/trophy00.trp, keeps its icons, and decrypts the trophy lists with the PS4's
trophy key (shadPS4's TrophyKey, entered in the launcher), in the game's language. Without the
key, only the icons. AES is in Python, as the AppImage has no crypto package.

When the game unlocks a trophy, the runtime records it in earned.tsv, the first time only, and
the overlay shows a card in the top-left corner in the style of the PS4's: the trophy's icon,
"You have earned a trophy." and its name. The platinum follows once every other trophy is
earned. The launcher's Trophies page lists them all, earned first, with the date; hidden ones
stay hidden until earned. BB_TROPHY_PREVIEW=<id> shows a trophy's notice at the game's first
trophy call, to see how it looks.
2026-10-11 15:35:42 +01:00
ayozetr e3c51c48aa Discord Rich Presence: the area and the co-op partners
Discord shows the area the player is in, and under it "Co-op with <partners>", "Online" or
"Offline". The game writes both into BB_PRESENCE_DIR, which run.sh makes new for each start:

- The runtime takes the area from the MapStudio files the game opens, one per map it loads.
  The player's own map comes first, then the maps around it (Central Yharnam brings the
  Forbidden Woods), so a map opened 5 s or more after the previous one starts a new load and
  names the area. It changes at loading screens only.
- The online module writes the online IDs of the players it has an established connection
  with, when a connection is established or removed.

The area names are those of Smithbox's Bloodborne map aliases (MIT); the Chalice Dungeons are
one name.
2026-10-11 15:11:09 +01:00
ayozetr 33393185b9 Support on Ko-fi: the About page, the README and GitHub's Sponsor button
A "Support this project" row in the launcher's About page opens ko-fi.com/ayozetr, the
README has a Support section, and .github/FUNDING.yml shows the link in GitHub's Sponsor
button.
2026-10-11 14:51:58 +01:00
ayozetr c294942db4 Launcher: the game folder names the release that is in it
The row said "Game folder (CUSA03173)" and the check's tooltip "Bloodborne CUSA03173,
version 1.09" whatever the folder held, from when only the European Game of the Year edition
ran. Both now name the title ID in the folder's param.sfo (CUSA00900, ...), or none without a
game.
2026-10-11 14:33:28 +01:00
obrikash 6c6974a742 Fix Vulkan startup when optional DLSS device extensions fail 2026-10-11 13:34:39 +01:00
ayozetr 83246710d7 0.51-linux.1, and what each tool is for
The launcher's version for the About page's updates. tools/README.md tells the tools the port,
the launcher and the AppImage use from bbport's development tools, kept as they are so that
its updates merge cleanly.
2026-10-11 02:53:20 +01:00
ayozetr b71eb7cfee Online: your own co-op server
shadPS4's public server never answers on its UDP port, so summons through it cannot connect
(deadinside28/bloodborne_pc#121). The Online page now chooses between that server and your
own, a shadnet-p2p server for a group of friends: its address and WebAPI, and seamless co-op,
which the server has to have on as well. The co-op port is a setting of its own instead of
SHADPS4_P2P_PORT in the extra variables, and the firewall warning uses it and says that UPnP
opens the port on the router only.

Test the connection pings the shadNet server's UDP port the way the game does and shows the
public address the server sees, or that it does not answer. It uses a made-up online ID: the
server keeps one address per account, and the player's own would replace the address of a
game running at the same time.

tools/shadnet-server builds shadnet-p2p in Docker on Debian 13, for the Qt 6.8 it needs
(Ubuntu 24.04 has 6.4), and keeps the configuration and accounts in a volume. With the
server's Tailscale address, it waits for the address before starting: shadnet-p2p keeps
running without its listeners when the address is missing.

Checked against shadnet-p2p 5a849a1: login, the UDP ping, matchmaking and a summon sign
reaching its summon service. docs/SERVER.md is the guide; ONLINE.md and TROUBLESHOOTING.md
cover online play and the common problems.
2026-10-11 01:41:53 +01:00
ayozetr b6c25e1fb4 Merge upstream 0.51 (master)
The online module from upstream replaces this fork's copy: the same shadp2p libraries, now
in gpu/bbnet as libbbnet.so, loaded only for online play, and UPnP opens the co-op port on
the router. Kept from this fork: game region, firewall warning, About page and updates,
cheats, Discord, title-ID mod folders and the sharun AppImage, which now bundles
libbbnet.so (BB_NET_MODULE). DLSS: the launcher's choice of NVIDIA's library looks in
BB_DLSS_DIR, the AppImage's copy. The launcher's new texts are translated.
2026-10-11 00:28:06 +01:00
deadinsideandClaude Opus 5.5 3c57da4198 0.51: online play (shadNet module), mouse look, DLSS in the AppImage, fixes, 399 MB AppImage
- Online play through shadNet as a separate module (gpu/bbnet -> libbbnet.so), loaded by the
  runtime only with BB_ONLINE=1; launcher Online page; UPnP maps the P2P port (#121).
- Mouse look and mouse/wheel bindings (#51, #52); quit from the overlay (#74, #116).
- DLSS bridge and NVIDIA's runtime library in the package; a newer one chosen in the launcher.
- Every retail release with update 1.09 gets the game profile and passes the game check
  (#119, PR #117).
- New memory model: motion blur smear (#122); 4 GB VRAM out-of-memory stop; title menu
  flicker above 1080p.
- HTTPS certificates in the AppImage; NVIDIA Wayland swapchain (PR #93); git build after 0.4
  (#124); nix-shell launcher arguments (PR #120); FSR 4.1.1 recording on SteamOS (PR #89).
- AppImage 925 -> 399 MB: Vulkan-only Mesa (RADV without LLVM, ANV), stripped game binary,
  slimmer MangoHud, SDL3 and launcher GTK.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-11 01:57:36 +03:00
ayozetr 0e2b626358 Mods and patches: every retail release, and a guide in English
A mod wrapped in a title ID folder was found only as CUSA03173/dvdroot_ps4; one made with the
US release (CUSA00900/dvdroot_ps4) was not. Any title ID folder is accepted now. Third-party
patch files listed six of the nine retail releases: a file for the Japanese release or the US
and Japanese The Old Hunters editions was skipped. The list is now the game check's.

docs/MODS.en.md is the guide to mods and third-party patches in English, based on bbport's
docs/MODS.md and checked against the code; the README and docs/README.md link to it, and the
Russian original moves to the development notes.
2026-10-10 22:33:31 +01:00
ayozetr b060b9fa2b Document which game releases run, and which have been checked
docs/COMPATIBILITY.md lists the nine retail releases the launcher accepts, with their title and
content IDs (from deadinside28/bloodborne_pc#117), and which ones have had their 1.09
executable checked: the US release (CUSA00900) and the European Game of the Year edition
(CUSA03173). The others are accepted on the expectation that they share that executable, and
the image hash still decides. It also lists what was tested with this fork. The README's note
on game files links to it.

game_check.py said the Asian The Old Hunters Edition (CUSA03023) shares the executable; nobody
has checked it, so it now says what is known.

docs/README.md is an index of docs/: what is for players, what is this fork's, and bbport's
development notes by topic, which stay as they are so that upstream updates merge cleanly.
2026-10-10 22:26:45 +01:00
209 changed files with 5916 additions and 1791 deletions

No files matched your search

+1
View File
@@ -0,0 +1 @@
ko_fi: ayozetr
+29 -4
View File
@@ -24,7 +24,9 @@ directly on the PC:
One step remains to the full Wine + DXVK model: make the new mode the default and remove the old
memory model (see below).
> **No game files are included.** You need your own dump of Bloodborne (CUSA03173, v1.09).
> **No game files are included.** You need your own dump of Bloodborne with update 1.09: any retail
> release (CUSA00900 in the US, CUSA03173 for the European Game of the Year edition, ...), as they
> share the same executable.
> This project is not affiliated with Sony Interactive Entertainment, FromSoftware or AMD.
**Status: experimental, playable.** The game boots, loads saves and plays (the Hunter's Dream
@@ -152,9 +154,10 @@ neither has nor includes.
Game of the Year edition's.
A dumped update is a separate folder: copy it over the base game, replacing files. The base
game alone (1.00) crashes at start (guest offset 0x20348b8); the launcher and `run.sh` check
the executable and say what is missing (`BB_SKIP_GAME_CHECK=1` skips the check). Some dumps
ship the 1.09 eboot.bin with Lance McDonald's 60 fps patch baked in; that one crashes when the
gestures menu opens, and the check asks for a clean eboot.bin (bbport has its own 60 fps).
the executable and say what is missing (`BB_SKIP_GAME_CHECK=1` skips the check). The other
retail releases (the US `CUSA00900`, the Asian `CUSA03023`, ...) run the same 1.09 executable. Some dumps ship it
with Lance McDonald's 60 fps patch baked in, which crashes when the gestures menu opens: the
check asks for a clean eboot.bin then (bbport has its own 60 fps).
- To build: GCC, CMake, Ninja, Python 3, glslang, SDL3, Vulkan headers and the libraries in
`shell.nix`. With [Nix](https://nixos.org) everything comes from `shell.nix` automatically.
@@ -284,6 +287,20 @@ DLSS gets the inputs FSR 3.1 gets (scene color, depth, motion vectors, jitter).
libraries, on other GPUs or with `BB_DLSS=0` it is listed as unavailable, and a DLSS setting falls
back to FSR 3.1.
On Linux, DLSS also needs NVIDIA's CUDA/UVM runtime. If device creation fails with the DLSS
extensions, the renderer retries without them and uses FSR 3.1. If `/dev/nvidia-uvm` is missing,
load the installed driver module with `sudo modprobe nvidia_uvm` and restart the game. Installing
the distribution's `nvidia-modprobe` package lets NVIDIA's libraries load the module when needed.
If `modprobe` reports `Key was rejected by service` with Secure Boot enabled, enroll the
module's signing key using the distribution's [MOK procedure](https://documentation.ubuntu.com/security/security-features/platform-protections/secure-boot/#mok-generation-and-signing-process).
The AppImage built with `DLSS_SDK_ROOT` carries the bridge and NVIDIA's library (NVIDIA's RTX SDK
license allows that in an application; its text is `NVIDIA-DLSS-LICENSE.txt` in the package). A
newer `libnvidia-ngx-dlss.so.<version>` (from the SDK's `lib/Linux_x86_64/rel`) is chosen in the
launcher: *Upscaler → DLSS: NVIDIA's library → Choose a file…*, as the FSR 4.1.1 DLL; it is
copied to `<user>/dlss/`, which the game prefers. A game's `nvngx_dlss.dll` is the Windows
library: NVIDIA's Linux driver does not load it.
From source the script takes its tools from the system (MinGW GCC, CMake, Ninja, Python 3,
SPIRV-Tools, Git) or from Nix; the AppImage has them prebuilt.
@@ -361,6 +378,14 @@ precise and slow, 0 off).
More in [docs/](docs); recent changes: [docs/CHANGES_0.4.md](docs/CHANGES_0.4.md) (in Russian),
[docs/CHANGES_2026-10-06.md](docs/CHANGES_2026-10-06.md).
**Online play (shadNet).** A separate module, `out/gpu/libbbnet.so` (`gpu/bbnet`: shadPS4's network
and PSN libraries from shadp2p, a shadPS4 fork, with the shadNet client), built when protobuf,
nlohmann_json, OpenSSL, zlib and miniupnpc are there (`shell.nix`) and included in the AppImage.
The launcher's *Online* page turns it on (`BB_ONLINE=1`): messages, bloodstains and ghosts come
from The Hunter's Dream, bells and summons go through a shadNet server (`srv.shadps4.net:31313` by
default) with a shadNet account (Online ID and password). Offline the module is never loaded; a
build without it plays offline only.
## Repository layout
| Path | Contents |
+28 -1
View File
@@ -23,7 +23,9 @@ bbport — это аналог Wine + DXVK, только для одной иг
До полной модели Wine + DXVK остался один шаг: новая модель и на NVIDIA, затем удаление старой
модели памяти (см. ниже).
> **Файлов игры в репозитории нет.** Нужен свой дамп Bloodborne (CUSA03173, v1.09).
> **Файлов игры в репозитории нет.** Нужен свой дамп Bloodborne с обновлением 1.09: любое издание
> из магазина (CUSA00900 в США, CUSA03173 — европейское Game of the Year, ...): у них один и тот же
> исполняемый файл.
> Проект не связан с Sony Interactive Entertainment, FromSoftware и AMD.
**Состояние: экспериментальный, играбельный.** Игра запускается, загружает сохранения и
@@ -146,6 +148,9 @@ bbport — это аналог Wine + DXVK, только для одной иг
Дамп обновления — отдельная папка: скопируйте её поверх базовой игры с заменой файлов. Одна
базовая игра (1.00) падает при запуске (guest offset 0x20348b8); лаунчер и `run.sh` проверяют
исполняемый файл и пишут, чего не хватает (`BB_SKIP_GAME_CHECK=1` отключает проверку).
Другие издания (американское `CUSA00900`, азиатское `CUSA03023`, ...) запускают тот же
исполняемый файл 1.09. В некоторых дампах в него уже вшит патч 60 FPS от Lance McDonald, из-за которого игра
падает при открытии меню жестов: проверка тогда просит чистый eboot.bin (у bbport свои 60 FPS).
- Для сборки: GCC, CMake, Ninja, Python 3, glslang, SDL3, заголовки Vulkan и библиотеки из
`shell.nix`. С [Nix](https://nixos.org) всё берётся из `shell.nix` автоматически.
@@ -254,6 +259,21 @@ Experimental от октября 2026; Proton 11.0 из Steam и GE-Proton 9 —
векторы движения, jitter). Без библиотек, на других видеокартах или с `BB_DLSS=0` он недоступен,
а выбранный DLSS заменяется на FSR 3.1.
На Linux DLSS также нужен CUDA/UVM из драйвера NVIDIA. Если устройство не создаётся с
расширениями DLSS, рендерер повторяет попытку без них и использует FSR 3.1. Если отсутствует
`/dev/nvidia-uvm`, загрузи установленный модуль командой `sudo modprobe nvidia_uvm` и перезапусти
игру. Пакет `nvidia-modprobe` из репозитория дистрибутива позволяет библиотекам NVIDIA загружать
модуль по мере необходимости.
Если при включённом Secure Boot команда `modprobe` сообщает `Key was rejected by service`,
зарегистрируй ключ подписи модуля по [процедуре MOK своего дистрибутива](https://documentation.ubuntu.com/security/security-features/platform-protections/secure-boot/#mok-generation-and-signing-process).
AppImage, собранный с `DLSS_SDK_ROOT`, содержит мост и библиотеку NVIDIA (лицензия RTX SDK от NVIDIA
это разрешает в составе приложения; её текст — `NVIDIA-DLSS-LICENSE.txt` в пакете). Более новая
`libnvidia-ngx-dlss.so.<версия>` (из `lib/Linux_x86_64/rel` в SDK) выбирается в лаунчере:
*Апскейлер → DLSS: библиотека NVIDIA → Выбрать файл…*, как DLL для FSR 4.1.1; она копируется в
`<user>/dlss/`, и игра берёт её первой. `nvngx_dlss.dll` из игр — библиотека для Windows: драйвер
NVIDIA на Linux её не загружает.
Скрипт из исходников берёт инструменты из системы (MinGW GCC, CMake, Ninja, Python 3,
SPIRV-Tools, Git) или из Nix; в AppImage они уже собраны.
@@ -331,6 +351,13 @@ VRAM считается не больше N МиБ: проверка повед
Подробнее — в [docs/](docs); последние изменения — [docs/CHANGES_0.4.md](docs/CHANGES_0.4.md),
[docs/CHANGES_2026-10-06.md](docs/CHANGES_2026-10-06.md).
**Игра по сети (shadNet).** Отдельный модуль `out/gpu/libbbnet.so` (`gpu/bbnet`: сетевые и PSN-библиотеки
shadPS4 из shadp2p, форка shadPS4, с клиентом shadNet); собирается, когда есть protobuf, nlohmann_json,
OpenSSL, zlib и miniupnpc (`shell.nix`), входит в AppImage. Включается на странице лаунчера *Онлайн*
(`BB_ONLINE=1`): сообщения, пятна крови и призраки — с The Hunter's Dream, колокола и призывы — через
сервер shadNet (по умолчанию `srv.shadps4.net:31313`) с учётной записью shadNet (Online ID и пароль).
Офлайн модуль не загружается; сборка без него играет только офлайн.
## Устройство репозитория
| Путь | Содержимое |
+30 -13
View File
@@ -7,14 +7,15 @@ This fork builds on [bbport](https://github.com/deadinside28/bloodborne_pc), the
by deadinside28. It adds the features of [Supermedo's Windows port](https://github.com/Supermedo/bloodborne_pc)
(online play, DLSS, cheats) brought to Linux, plus a few of its own.
> **No game files are included.** You need your own decrypted dump of Bloodborne 1.09: the
> European Game of the Year edition (`CUSA03173`) or the US release (`CUSA00900`). This project is
> not affiliated with Sony Interactive Entertainment or FromSoftware.
> **No game files are included.** You need your own decrypted dump of Bloodborne with update
> 1.09, from a retail release: [which ones, and which have been checked](docs/COMPATIBILITY.md).
> This project is not affiliated with Sony Interactive Entertainment or FromSoftware.
## Features
- **Online play (beta)** through [The Hunter's Dream](https://thehuntersdream.com) and shadNet:
messages, bloodstains, ghosts, bells and summons. Linux and Windows players can play together.
messages, bloodstains, ghosts, bells and summons. Linux and Windows players can play together,
through shadPS4's public server or [one of your own](docs/SERVER.md).
- **Upscaling:** AMD FSR 3.1, FSR 4 and FSR 4.1.1, **NVIDIA DLSS** on GeForce RTX, and
native-resolution TAA.
- **Unlocked frame rate**, capped at your display's refresh rate up to 120 FPS (above that the
@@ -29,9 +30,13 @@ by deadinside28. It adds the features of [Supermedo's Windows port](https://gith
menu without the motion-control icons.
- **Cheats and gameplay tweaks:** never die, stealth, silent steps, enemy control, camera
distance, ragdoll physics and more.
- **Trophies:** a notice in the game, in the style of the PS4's, and a Trophies page in the
launcher with every trophy, from your own dump. Their names and descriptions need the PS4's
trophy key (shadPS4's TrophyKey), which you enter in the launcher; without it, only the icons.
- **Game effects** on and off, **mods** and community **patches**, loaded without changing the
game files.
- **Add to Steam** in one click (native or Flatpak Steam), and **Discord Rich Presence**.
game files ([how](docs/MODS.en.md)).
- **Add to Steam** in one click (native or Flatpak Steam), and **Discord Rich Presence** with the
area you are in and your co-op partners.
- **AppImage:** one file with everything inside, for any distribution and the Steam Deck. It
updates itself: the launcher's **About** page checks this repository's releases and installs
a new AppImage over the old one.
@@ -71,18 +76,25 @@ With [Nix](https://nixos.org), `bash build.sh` gets every dependency from `shell
### Online play
1. Register a shadNet account at [shadnet.shadps4.net](https://shadnet.shadps4.net).
2. In the launcher, open **Online**, turn on **Play online** and enter your account name (not
your email) and password. **Test the connection**: all three servers should be reachable.
1. Register a shadNet account at [shadnet.shadps4.net](https://shadnet.shadps4.net), or get one
from the owner of your group's own server.
2. In the launcher, open **Online**, turn on **Play online**, choose the shadNet server and enter
your account name (not your email) and password. **Test the connection**: every line should
be green.
3. Start the game and choose online at the title screen.
Everyone in a session needs game version 1.09 and the same servers. Turn cheats off when you
play with others.
Co-op connects the players directly over UDP. With ufw or firewalld on, the launcher's **Online**
page says so and gives the commands: pin the port with `SHADPS4_P2P_PORT=3658` in the extra
variables, open it (`sudo ufw allow 3658/udp`), and for UPnP let the router's answers in
(`sudo ufw allow from <router> proto udp`).
**Co-op needs your own server for now:** shadPS4's public server does not answer on its UDP port,
so summons do not connect through it (messages, bloodstains and ghosts do).
[docs/SERVER.md](docs/SERVER.md) sets one up with Docker and Tailscale; it has been tested with a
Linux and a Windows player.
Co-op connects the players directly over UDP. UPnP opens the port on the router by itself; with
ufw or firewalld on, the launcher's **Online** page says so and gives the commands: pin the
**Co-op port** (for example 3658), open it (`sudo ufw allow 3658/udp`), and for UPnP let the
router's answers in (`sudo ufw allow from <router> proto udp`). [More in docs/ONLINE.md](docs/ONLINE.md).
### DLSS
@@ -118,6 +130,11 @@ Keyboard**. **Gestures menu without motion-control icons** cleans up the gesture
prompts are put into your own game's menu files at each start, and nothing in the game folder
changes.
## Support
If this fork is useful to you and you would like to support it, you can on
[Ko-fi](https://ko-fi.com/ayozetr). The port itself is deadinside28's work (see below).
## Credits
- [deadinside28/bloodborne_pc](https://github.com/deadinside28/bloodborne_pc): **bbport**, the
+16 -6
View File
@@ -34,16 +34,26 @@ mkdir -p pgo
if [[ ! -f gpu/third_party/fsr-vulkan/CMakeLists.txt || ! -f gpu/third_party/imgui/imgui.h ]]; then
git submodule update --init --recursive
fi
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"
fi
done
# 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" >/dev/null
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 > out/gpu-build.log 2>&1; then
if ! ninja -C out/gpu bbgpu $(grep -q "^build bbnet:" out/gpu/build.ninja && echo bbnet) > 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
+109
View File
@@ -0,0 +1,109 @@
**English** · [Русский](#русский)
bbport is the counterpart of Wine + DXVK for a single game: Bloodborne (v1.09) on Linux.
Changes since [0.5](https://github.com/deadinside28/bloodborne_pc/releases/tag/0.5); details and
measurements: [CHANGES_after_0.5.md](https://github.com/deadinside28/bloodborne_pc/blob/master/docs/CHANGES_after_0.5.md) (Russian).
Questions about this project: Discord https://discord.gg/KYZRKk9CB — not the shadPS4 server.
### New
- **Online play (shadNet)**, as a separate module (`libbbnet.so`, loaded only when online play is
on): messages, bloodstains and ghosts from The Hunter's Dream, bells and summons through a
shadNet server (`srv.shadps4.net:31313` by default) with a shadNet account. Launcher → *Online*:
servers, account, UPnP, connection test. The router port is opened by UPnP (#121). The same
servers as the Windows port. The network and PSN libraries come from shadp2p (a shadPS4 fork,
GPL-2.0) by way of the Linux and Windows forks of bbport.
- **Mouse look**: click into the game to take the mouse, F1 releases it; mouse buttons and the
wheel can be bound like keys (Mouse Left = R1, Mouse Right = L2, Middle = R3, side buttons
R2/L1, wheel = quick items). Launcher → *Controls*: mouse look, sensitivity, invert Y (#51, #52).
- **DLSS in the AppImage** (NVIDIA GeForce RTX): the bridge and NVIDIA's DLSS 310.9.1 library are
included (NVIDIA's RTX SDK license allows it within an application; its text is in the package).
A newer `libnvidia-ngx-dlss.so.*` can be chosen in the launcher (*Upscaler → DLSS: NVIDIA's
library*), like the FSR 4.1.1 DLL.
- **Every retail release** of Bloodborne with update 1.09 is accepted (US CUSA00900, EU, UK, JP,
Asia and The Old Hunters editions; PR #117); an `eboot.bin` with a 60 fps patch baked in is
reported.
- **Quit the game** from the overlay (Insert / L3+R3; press twice) — #74, #116.
### Fixes
- The US release (and other regions) crashed with code 139 on entering the world in the new
memory model: they ran without the game's profile (#119).
- Motion blur smeared the whole frame while the camera turned in the new memory model (#122).
- Cards with 4 GB (NVIDIA): "Failed to allocate 64 MiB for guest memory copies" stopped the game;
now it frees textures sooner and uses other memory instead.
- The main menu flickered with output resolutions above 1080p (live resolution).
- Online, "Could not get information from the Bloodborne server" in the AppImage on NixOS (HTTPS
certificates).
- NVIDIA on Wayland: the swapchain is recreated through `oldSwapchain` (PR #93).
- Building from git after updating from 0.4: "patch failed: src/ffx_vk_fsr4_v07.c" (#124).
- `bb-launcher.sh --play` through nix-shell (PR #120); FSR 4.1.1 recording from the AppImage on
SteamOS (PR #89).
### Smaller download
The AppImage is **399 MB instead of 925 MB**: only Mesa's Vulkan drivers (RADV without LLVM and
ANV) instead of all of Mesa, no debug info in the game binary, MangoHud without its 32-bit half,
the launcher's GTK without GStreamer.
**Known limits:** online login and summons were not tested by the author (no shadNet account);
the UDP side of the public shadNet server did not answer in #121. Mouse look and DLSS need
testing on more systems.
The AppImage contains no game files. AMD's FSR 4 model assets are not bundled. `SHA256SUMS`
accompanies the download.
## Русский
bbport — аналог Wine + DXVK для одной игры: Bloodborne (v1.09) на Linux. Изменения после
[0.5](https://github.com/deadinside28/bloodborne_pc/releases/tag/0.5); подробности и замеры —
[CHANGES_after_0.5.md](https://github.com/deadinside28/bloodborne_pc/blob/master/docs/CHANGES_after_0.5.md).
Вопросы по проекту: Discord https://discord.gg/KYZRKk9CB — не сервер shadPS4.
### Новое
- **Игра по сети (shadNet)** — отдельным модулем (`libbbnet.so`, загружается, только когда онлайн
включён): сообщения, пятна крови и призраки — с The Hunter's Dream, колокола и призывы — через
сервер shadNet (по умолчанию `srv.shadps4.net:31313`) с учётной записью shadNet. Лаунчер →
*Онлайн*: серверы, учётная запись, UPnP, проверка соединения. Порт на роутере открывается по UPnP
(#121). Серверы те же, что у Windows-версии. Сетевые и PSN-библиотеки — из shadp2p (форк shadPS4,
GPL-2.0), через Linux- и Windows-форки bbport.
- **Камера мышью**: щелчок в окне игры захватывает мышь, F1 — отпускает; кнопки мыши и колесо
назначаются как клавиши (левая — R1, правая — L2, средняя — R3, боковые — R2/L1, колесо —
быстрые предметы). Лаунчер → *Управление*: камера мышью, чувствительность, инверсия (#51, #52).
- **DLSS в AppImage** (NVIDIA GeForce RTX): мост и библиотека DLSS 310.9.1 от NVIDIA в пакете
(лицензия RTX SDK разрешает это в составе приложения; её текст — в пакете). Более новую
`libnvidia-ngx-dlss.so.*` можно выбрать в лаунчере (*Апскейлер → DLSS: библиотека NVIDIA*), как DLL
для FSR 4.1.1.
- **Любое розничное издание** Bloodborne с обновлением 1.09 (США CUSA00900, Европа, Великобритания,
Япония, Азия и издания с The Old Hunters; PR #117); о `eboot.bin` со вшитым патчем 60 FPS
сообщается.
- **Выход из игры** из оверлея (Insert / L3+R3; нажать дважды) — #74, #116.
### Исправления
- Американское и другие издания падали с кодом 139 при входе в мир в новой модели памяти: они шли
без профиля игры (#119).
- Размытие в движении размазывало весь кадр при повороте камеры в новой модели памяти (#122).
- Карты на 4 ГБ (NVIDIA): «Failed to allocate 64 MiB for guest memory copies» останавливало игру;
теперь текстуры освобождаются раньше, используется другая память.
- Мерцание главного меню при выводе выше 1080p (живая смена разрешения).
- Онлайн: «Не удалось получить информацию от сервера Bloodborne» в AppImage на NixOS (сертификаты
HTTPS).
- NVIDIA на Wayland: swapchain пересоздаётся через `oldSwapchain` (PR #93).
- Сборка из git после обновления с 0.4: «patch failed: src/ffx_vk_fsr4_v07.c» (#124).
- `bb-launcher.sh --play` через nix-shell (PR #120); запись FSR 4.1.1 из AppImage на SteamOS (PR #89).
### Меньше скачивать
AppImage — **399 МБ вместо 925 МБ**: из Mesa только Vulkan-драйверы (RADV без LLVM и ANV), без
отладочной информации в бинарнике игры, MangoHud без 32-битной части, GTK лаунчера без GStreamer.
**Ограничения:** вход в shadNet и призыв автор не проверял (нет учётной записи); UDP-часть
публичного сервера shadNet в #121 не отвечала. Камеру мышью и DLSS нужно проверить на большем числе
систем.
Файлов игры в AppImage нет. Ассеты моделей FSR 4 от AMD не входят. К загрузке прилагается
`SHA256SUMS`.
+159
View File
@@ -0,0 +1,159 @@
# Изменения после 0.5 (с 2026-10-10)
Замеры — RX 7800 XT / RADV, сохранение пользователя (Соборный округ), 1080p.
## Все розничные издания получают профиль игры (#119)
- Профиль Bloodborne (`gpu/games/bloodborne.cpp`) выбирался только для CUSA03173. Американское
издание (CUSA00900) и остальные регионы запускают тот же исполняемый файл 1.09, но шли без
профиля, и новая модель падала при входе в мир: `Guest fault ... at guest offset 0x2085xxx,
address (nil)` в аллокаторе игры (#119, RX 7600, US-издание).
- Воспроизведено у себя на CUSA03173 с `BB_GAME_PROFILE=none`: то же падение (`0x208596a`) при
входе в мир. С профилем, но без перехватов (`BB_GUEST_HOOKS=0`) — не падает: спасает
`DynamicWriters` — код аллокатора, чьи служебные данные лежат в памяти GPU; без этой отметки
их блоки уходят в VRAM-копию.
- Профиль, проверка игры (`scripts/game_check.py`), патчи (`scripts/patches.py`), «звуковой
фикс» сохранений и папки модов теперь знают все издания: CUSA00900, CUSA00207, CUSA00208,
CUSA00299, CUSA01363 и издания с The Old Hunters CUSA03179, CUSA03173, CUSA03014, CUSA03023.
- Проверка игры: другие регионы базовой игры без обновления просят 1.09 вместо «поддерживается
только CUSA03173»; eboot.bin со вшитым патчем 60 FPS (падает в меню жестов) — отдельное
сообщение (PR #117).
- Осталось: общий путь без профиля должен не падать сам (служебные данные аллокатора в
VRAM-копии). Сейчас он нужен только для чужих игр.
## Размытие в движении на весь кадр в новой модели (#122)
- С включённым размытием в движении (по умолчанию) кадр при повороте камеры размазывался целиком,
в старой модели — нет (#122, RX 9060 XT). Воспроизведено: резкость кадра во время поворота
(стандартное отклонение лапласиана) 6,9 против 8,5–12 в старой модели.
- Поиск: `BB_GARLIC_VRAM_RANGE=начало,конец` (новый диагностический ключ: VRAM-копии только в
этом диапазоне) и деление диапазона пополам — блок 64 КиБ `0x104ff00000`. Его читает только
видеочип (буфер 11,4 МиБ каждый кадр), записей буферами и процессором нет: это память
рендер-таргета, который игра потом читает как буфер.
- Причина: выгрузка изображения в память игры шла через staging и отложенную запись процессора,
когда у этой памяти была VRAM-копия; копия обновлялась лишь после той записи (инвалидацией) —
буфер читал данные прошлых кадров. Теперь видеочип копирует изображение и в арену (VRAM-копию)
в порядке потока; в память игры — как раньше. И `IsRegionGpuModified` считает изменённым то,
что видеочип записал в VRAM-копию (`gpu_written_bytes`, не на месте): без этого обновление после
записи процессора поверх затирало копию старыми байтами (`BB_GPU_DATA_CHECK=0` — как раньше).
Нужны обе правки. После: 11,9–13,0, как в старой модели; FPS тот же (127–131 в обоих
вариантах, по три запуска).
## Нехватка VRAM на 4 ГБ больше не останавливает игру
- RTX 3050 4 ГБ, старая модель (Авто на NVIDIA), 0.5: три падения за вечер —
`Failed to allocate 64 MiB for guest memory copies: ErrorOutOfDeviceMemory`. Запасного типа
памяти (системной) для арены нет: разреженные буферы NVIDIA берут только VRAM. В pre5
сборщик текстур стал держать текстуры по 5 с (FPS не падал со временем), и на 4 ГБ VRAM
заканчивалась.
- Теперь: блок поменьше (ровно запрошенный), затем любой другой тип памяти, к которому можно
привязать арену; и 30 с сборщик под давлением снова выселяет по отправкам, как до 0.5. Он же
делает так сам, когда занято больше 92 % бюджета драйвера (`VK_EXT_memory_budget`, раз в
секунду). Проверить можно только на такой карте.
## Выход из игры с геймпада (#74, #116)
- Оверлей (Insert или L3+R3): кнопка «Выйти из игры», второе нажатие подтверждает; игра
закрывается как по кнопке окна.
## Мышь
- Камера мышью: щелчок в окне игры захватывает мышь (относительный режим SDL), F1 или уход из
окна — отпускает; меню настроек и ввод имени тоже отпускают. Движение мыши — правый стик:
отклонение по скорости мыши (~1000 пикселей/с — полный поворот при чувствительности 1), за
60 мс спадает; движущаяся мышь сразу проходит мёртвую зону игры (`BB_MOUSE_DEADZONE`, 16 из
127), так что медленное прицеливание тоже поворачивает камеру. Одинаково при любом FPS.
- Кнопки мыши и колесо — те же «клавиши» в привязках: `Mouse Left` R1, `Mouse Right` L2 (огнестрел),
`Mouse Middle` R3 (захват цели), `Mouse X1` R2, `Mouse X2` L1, колесо — крестовина вверх/вниз
(быстрые предметы); каждое деление колеса — короткое нажатие. Кнопки работают только при
захваченной мыши: щелчок, который её захватывает, не атакует.
- bbport.ini: `mouse_look=0/1`, `mouse_sensitivity` (0.05–20), `mouse_invert_y`; лаунчер —
*Управление*: «Камера мышью», чувствительность, инверсия; «Клавиатура и мышь» — назначение
кнопок, «Назначить» принимает и кнопку мыши/колесо. Основа — PR #108 (виртуальный стик от
движения мыши); раскладка клавиатуры не менялась.
## Прочее
- Swapchain пересоздаётся через `oldSwapchain` (PR #93): на NVIDIA под Wayland пересоздание
падало с «Surface already has a tearing controller».
- `launcher/bb-launcher.sh` передаёт аргументы (`--play`) и через nix-shell (PR #120).
- Запись FSR 4.1.1 из AppImage на SteamOS и других дистрибутивах (PR #89): запись на хосте
через systemd, повтор с GPU, представленным как RX 7800 XT, если DLL не предлагает FSR 4.1.
- Лаунчер: у DLSS — подсказка, есть ли он в этой сборке (в AppImage его нет: DLSS SDK от NVIDIA
не распространяется, игра включает FSR 3.1).
## DLSS в AppImage и своя библиотека NVIDIA
- Сборка с `DLSS_SDK_ROOT` (DLSS SDK 310.9.1 с github.com/NVIDIA/DLSS) кладёт в пакет мост
`libbbport_dlss.so`, `libnvidia-ngx-dlss.so.310.9.1` и `NVIDIA-DLSS-LICENSE.txt` (лицензия RTX
SDK разрешает распространение в составе приложения, не отдельно). Тестовый AppImage:
`dist/…-test-1010-dlss.AppImage`.
- Лаунчер, *Апскейлер → DLSS: библиотека NVIDIA → Выбрать файл…* — как DLL для FSR 4.1.1:
`libnvidia-ngx-dlss.so.<версия>` копируется в `<user>/dlss/`, игра берёт её раньше встроенной
(лог: `DLSS: NVIDIA's library from …`). Выбранная `nvngx_dlss.dll` — подсказка, что нужна
библиотека для Linux. Мост ищется рядом с `bb-probe`, затем в `<user>/dlss/`.
- Мост собирается и с защитными флагами Nix (`-Werror=format-security`).
- Проверено на RX 7800 XT только до «not an NVIDIA GPU»: путь к библиотеке (встроенной и
своей) выбирается верно. Сам DLSS — на карте NVIDIA RTX.
## Сборка из git после обновления с 0.4 (#124)
- `build.sh` останавливался: «patch failed: src/ffx_vk_fsr4_v07.c:35» — в подмодуле FSR-Vulkan
оставался применённым патч прошлой версии, а новый не применялся ни вперёд, ни назад. Теперь
подмодуль в этом случае сбрасывается и патчи применяются заново (проверено на копии в таком
состоянии).
## Онлайн (shadNet) — отдельным модулем
- `gpu/bbnet` → `out/gpu/libbbnet.so`: сетевые и PSN-библиотеки shadPS4 из shadp2p (форк shadPS4,
GPL-2.0) с клиентом shadNet, перенесены из Linux-форка bbport с онлайном (а тот — из Windows-порта).
Модуль собирается отдельной целью, его C++ скрыт (`-fvisibility=hidden`, `-Bsymbolic`), наружу —
только `bbnet_init` и `bbnet_resolve` (`gpu/bbnet/bbnet.h`). Свои заголовки модуля
(`gpu/bbnet/include`) только дополняют общие: в `gpu/shim` и `gpu/shadps4` ничего не менялось.
- Рантайм (`src/runtime_net.c`): с `BB_ONLINE=1` на первом сетевом/PSN-импорте загружает модуль
(`dlopen`, `RTLD_LOCAL`; `BB_NET_MODULE` — другой путь), отдаёт ему данные игры и гостевые потоки
для обратных вызовов NP; трофеи, голос и диалоги магазина остаются в рантайме. Без `BB_ONLINE`
модуль не загружается; без модуля или если он не стартовал — офлайн, как раньше.
- Сборка: protobuf, nlohmann_json, OpenSSL, zlib, miniupnpc (`shell.nix`); без них модуль не
собирается (`BB_NET=OFF` — вручную), порт собирается как раньше. AppImage содержит модуль.
- `run.sh`: перенаправления адресов (`scripts/online.py`: сервер игры → The Hunter's Dream,
знаки призыва → WebAPI shadNet), сервер shadNet по умолчанию `srv.shadps4.net:31313`.
- Лаунчер: страница *Онлайн* (сервер игры, сервер кооператива и WebAPI, учётная запись shadNet,
UPnP, проверка соединения); `settings.json` — только для владельца (0600, там пароль).
- UPnP: порт P2P теперь открывается на роутере, когда транспорт готов, и закрывается при выходе
(#121: `AddMapping` не вызывался нигде).
- Проверено: `tests/test_online.c` (импорты сети и NP → модуль, трофеи → рантайм); игра с
`BB_ONLINE=1` без учётной записи доходит до уровня (модуль: 1399 функций; «no users connected
to shadNet»). Вход в shadNet и призыв не проверены: нет учётной записи, а UDP-часть публичного
сервера, по #121, не отвечает.
- HTTPS в AppImage: «Не удалось получить информацию от сервера Bloodborne» — проверка сертификата
The Hunter's Dream проваливалась (`SSL server verification failed`): OpenSSL из Nix берёт корневые
сертификаты из `/etc/ssl/certs/ca-certificates.crt`, а на NixOS это ссылка в `/nix/store` хоста,
которого внутри AppImage не видно. Обёртки пакета теперь задают `SSL_CERT_FILE` на свой пакет
сертификатов (`nss-cacert`), если указанный не читается; `run.sh` из исходников берёт системный.
Лаунчер: текст ошибки в проверке соединения не терялся из-за разметки (`<urlopen error …>`), значки
— из темы Adwaita.
## Мерцание главного меню при выводе выше 1080p
- С живой сменой разрешения (вывод 3840×2160 на мониторе 2560×1080) главное меню мерцало: часть
кадров показывалась в родных 1920×1080 игры, остальные — с интерфейсом в разрешении вывода
(4 из 50 снимков). `BB_UI_TRACE=1` (новая диагностика: отрисовки кадров без интерфейса в
разрешении вывода) показал: пока меню анимирует подсветку, игра рисует его другими шейдерами
Scaleform (`bb4d5f8c`, `e94b5b06`, `9951d199`, `44072322`, `a334a845`), а не `09957251`; их не было в
списке шейдеров интерфейса (`ui_composition.h`), и такие кадры не собирались в разрешении
вывода. После: 0 из 80; в уровне картинка та же.
## AppImage меньше
- В пакете были весь Mesa с LLVM (~800 МБ: нужны только Vulkan-драйверы RADV и ANV), полный GCC
и заголовки Vulkan (их пути в отладочной информации `bb-probe`), 32-битная половина MangoHud
(вторые glibc, gtk3, icu, perl) и GStreamer у GTK4 лаунчера. Теперь: свои RADV (без LLVM, ACO)
и ANV без остального Mesa, `bb-probe` без отладочной информации, MangoHud 64-битный, GTK4 без
GStreamer, печати и tracker.
- Ещё: SDL3 без зашитого zenity (тот тянул вторую GTK4 с GStreamer; теперь zenity хоста, если
есть), libdecor без плагина GTK 3 (у SDL3 и у glfw MangoHud; рамки рисует его cairo-плагин),
MangoHud без xdg-utils (Perl; `xdg-open` хоста). Сборка своей Mesa включает Dozen только потому,
что рецепт nixpkgs ждёт его выход `spirv2dxil`; в пакет он не попадает.
- Итог: AppImage 925 → 399 МБ, пакет без сжатия 2,85 → 1,06 ГБ. Проверено: лаунчер открывается,
игра из пакета стартует на встроенном RADV до титульного экрана.
+48
View File
@@ -0,0 +1,48 @@
# Game compatibility
bbport runs Bloodborne for PS4 with **update 1.09**. Its hooks and patches use the addresses of
one executable: the launcher hashes the loaded `eboot.bin` image and runs only that one 1.09
executable (`scripts/game_check.py`). A dump that passes the check runs; one that does not is
told why (no 1.09 update, another executable, or an `eboot.bin` with Lance McDonald's 60 fps
patch baked in).
## Releases the launcher accepts
Every retail release of Bloodborne. Title and content IDs as listed in
[deadinside28/bloodborne_pc#117](https://github.com/deadinside28/bloodborne_pc/pull/117).
| Edition | Region | Title ID | Content ID | 1.09 executable checked |
|---|---|---|---|---|
| Bloodborne | US | `CUSA00900` | `UP9000-CUSA00900_00-BLOODBORNE000000` | Yes |
| Bloodborne | Europe | `CUSA00207` | `EP9000-CUSA00207_00-BLOODBORNE0000EU` | Not yet |
| Bloodborne | UK | `CUSA00208` | `EP9000-CUSA00208_00-BLOODBORNE0000UK` | Not yet |
| Bloodborne | Japan | `CUSA00299` | `JP9000-CUSA00299_00-BLOODBORNE0000JP` | Not yet |
| Bloodborne | Asia | `CUSA01363` | `HP9000-CUSA01363_00-BLOODBORNE0000AS` | Not yet |
| The Old Hunters Edition | US | `CUSA03179` | `UP9000-CUSA03179_00-BLOODBORNE000000` | Not yet |
| Game of the Year Edition | Europe | `CUSA03173` | `EP9000-CUSA03173_00-BLOODBORNE0000EU` | Yes |
| The Old Hunters Edition | Japan | `CUSA03014` | `JP9000-CUSA03014_00-BLOODBORNE0000JP` | Not yet |
| The Old Hunters Edition | Asia | `CUSA03023` | `HP9000-CUSA03023_00-BLOODBORNE0000AS` | Not yet |
*Checked* means a dump of that release with update 1.09 had exactly the executable bbport runs.
The others are accepted on the expectation that every release shares the same 1.09 executable;
if one does not, the launcher says so instead of starting a game that would crash. A report of
how yours goes is welcome either way.
The alpha tests (`CUSA01318`, `CUSA01322`, `CUSA01333`, `CUSA01335`) are not supported.
The Game of the Year and The Old Hunters editions include the DLC. With a base game, dump the
add-ons too and choose their folder in the launcher (see the README's *DLC* section).
## Tested with this fork
On Linux (CachyOS, NVIDIA GeForce RTX 3060), with the US release (`CUSA00900`):
- The base game with update 1.09 and the add-ons dumped separately (The Old Hunters and the two
messenger add-ons), from the launcher's DLC folder.
- A dump whose `eboot.bin` had Lance McDonald's 60 fps patch baked in: the launcher reports it,
and the clean 1.09 `eboot.bin` runs.
- Both regional texts through *Game region*: Spanish from Spain (Europe) and Latin American
Spanish (the Americas).
The European Game of the Year edition (`CUSA03173`) is the release the original bbport is
developed and tested with.
+109
View File
@@ -0,0 +1,109 @@
# Mods and third-party patches
Both are on the launcher's **Settings** page and apply at the next start. The game folder itself
is never changed.
## File mods
The **Mods** group has the folder, a **Load mods** switch, and the list of mods: each one can be
turned on or off and moved up or down. The lowest mod that is on wins: when two mods replace the
same file, the log says which one replaced the other.
The mods folder is `~/.local/share/bbport/mods/` with the AppImage (`mods/` in the data
directory when running from the repository). Extract each mod into a folder of its own:
```text
mods/
Mod name/
dvdroot_ps4/
chr/...
param/...
menu/...
```
These layouts work as well:
- `Mod name/app0/dvdroot_ps4/...`, and `Mod name/<title ID>/dvdroot_ps4/...` with whichever
release the mod was made for (`CUSA03173`, `CUSA00900`, ...).
- One extra wrapper folder, as extracting an archive into a folder of its name leaves it:
`Mod name/Mod name v1.2/dvdroot_ps4/...` (readme files and pictures may sit next to it).
- The game's folders without `dvdroot_ps4`: `Mod name/chr/...`, `Mod name/parts/...` (`chr`,
`parts`, `map`, `menu`, `msg`, `param`, `sfx`, `sound`, `font` and the other folders of
`dvdroot_ps4`).
Upper or lower case does not matter: a mod made on Windows with
`DVDROOT_PS4/Chr/C0000.chrbnd.dcx` replaces the game's `dvdroot_ps4/chr/c0000.chrbnd.dcx`.
The log shows how many game files the mods replaced and added, e.g.
`Mods: 12 game files replaced, 0 added`. A mod meant to replace files that says
`0 game files replaced` has its files in the wrong place.
What works: ready-made replacements of `dvdroot_ps4` files (textures, models, params,
interface, sound, fonts). What does not:
- ZIP or 7z archives: extract them first.
- Two mods changing different parts of the same `.dcx` or `.bnd` file: the last one replaces
it whole, the files are not merged.
- Mods that replace `eboot.bin`, `sce_module` or `sce_sys`, DLL injectors and script plugins.
Changes to the game's code are patches (below).
- Symbolic links inside a mod.
Whether a mod works with Bloodborne 1.09 is up to its author.
A shadPS4-style folder next to the game folder, `<game folder>-mods/dvdroot_ps4/...` (for
example `CUSA03173-mods` next to `CUSA03173`), is loaded too, before the mods in the list. You
can also choose a folder that holds `dvdroot_ps4` directly as the mods folder: it is then loaded
as one mod. **Load mods** turns all of them off. The launcher's button prompts and gestures
menu work the same way, as files laid under the mods; they are settings of their own and stay
on when mods are off.
### How it works
For each start, the data directory gets a merged tree of links, `out/mod-game-*`: the game sees
the mods' files where they replace its own and the original files everywhere else. `/app0` is
read-only, and saves go to the usual folder. The tree is removed when the game exits normally
or the launcher stops it; one left behind by a crash is not reused.
The order and the mods turned off are kept in `mods.json` in the data directory:
```json
{"order": ["First", "Second"], "disabled": ["First"]}
```
New folders are turned on and added at the end, in alphabetical order.
From a terminal:
```sh
BB_GAME_DIR=/path/to/game BB_MODS_DIR=/path/to/mods bash run.sh
BB_GAME_DIR=/path/to/game BB_MODS_ENABLED=0 bash run.sh
```
`BB_MODS_CONFIG` sets another `mods.json`. `BB_MOD_TRACE=1` (with `BB_MODS_DIR`) logs the
first reads of files that come from mods, to see whether a mod is being used.
## Third-party patches
The **Third-party patches** group loads patches in the shadPS4/GoldHEN XML format from the
patches folder: `~/.local/share/bbport/patches/` with the AppImage, or another folder chosen in
the launcher.
- Only patches for version `01.09` of `eboot.bin` are listed. Files for other games are
skipped: a file applies when it lists any retail release of Bloodborne, or none.
- Each patch starts on or off as the file says (`isEnabled`); the choice in the launcher is
kept in `patches.json` in the data directory:
```json
{"enabled": ["file.xml/Patch name"], "disabled": ["file.xml/Other patch"]}
```
- Lines of type `bytes`, `bytes16`, `bytes32`, `bytes64`, `float32`, `float64`, `utf8` and
`utf16` work. A patch with a `mask` line (a pattern search) or an address outside the
executable is skipped whole, and the log says so.
- They apply after bbport's own patches (`patches/Bloodborne.xml`), so where both change the
same bytes, the third-party patch wins.
- Patches that replace pointers in tables, such as *60 FPS++*, are moved to where the game is
loaded.
From a terminal: `BB_PATCHES_DIR=/path BB_PATCHES_CONFIG=/path/patches.json bash run.sh`.
This guide is based on bbport's [MODS.md](MODS.md) (Russian), by deadinside28.
+76
View File
@@ -0,0 +1,76 @@
# Online play and co-op
Online play is a beta. Messages, bloodstains and ghosts come from the community game server,
[The Hunter's Dream](https://thehuntersdream.com). Bells and summons go through a shadNet server,
and then the players' games connect to each other directly. Linux and Windows players can play
together: everyone needs the game at version 1.09 and the same servers.
> **Co-op does not connect through shadPS4's public server.** It does not answer the UDP ping
> that tells it each player's address, so a summon times out
> ([deadinside28/bloodborne_pc#121](https://github.com/deadinside28/bloodborne_pc/issues/121));
> the shadPS4 team does not support forks. Messages, bloodstains and ghosts work. For co-op, a
> group runs its own server: [SERVER.md](SERVER.md). *Test the connection* tells which case
> yours is: the shadNet server's UDP line is red on the public server.
## Account
1. On shadPS4's public server, register at [shadnet.shadps4.net](https://shadnet.shadps4.net).
On your own server, its owner creates the account ([SERVER.md](SERVER.md)).
2. In the launcher's **Online** page, turn on **Play online**, choose the **shadNet server**
(shadPS4's public one or your own, with its address), and enter the **account name** (not the
email) and the password. The password is kept on this computer with the launcher's settings.
3. **Test the connection**: the game server, the shadNet server, its UDP port and its WebAPI
should all answer.
If the game says you are not signed in to PlayStation Network, the shadNet login failed. The
usual cause is the password: the log then has a shadNet login error (code 8 is a wrong
password). *Test the connection* only checks that the servers answer, not the account.
## Summoning in the game
- The host rings the **Beckoning Bell** (one Insight each time); the helper rings the **Small
Resonant Bell**.
- Use the same **password** in the game's network settings, so you find each other whatever
your levels.
- Be in the same area, close to each other, with the area's boss still alive in the host's
world.
## Ports
Co-op traffic is UDP, straight between the players' computers. With your own server on
Tailscale ([SERVER.md](SERVER.md)) it goes through Tailscale: turn **UPnP** off and skip this
section. Otherwise each player has to be reachable from the Internet:
1. **The router.** With **UPnP** on (the default), the game opens its port on the router itself:
the log says `UPNP: mapped UDP port <port>`. A router without UPnP needs a port forward by
hand (UDP, the pinned port below, to your computer's LAN address).
2. **Pin the port** when you open it by hand or in a firewall: **Co-op port (UDP)** in the
Online page, for example 3658 (0, the default, is a random port each time). The log then says
`P2P transport ready: UDP physical_port=3658`.
3. **Open it in the firewall.** UPnP opens the port on the router only, not in this computer's
firewall. With ufw or firewalld on, the launcher's **Online** page says
so and gives the commands. For ufw:
```sh
sudo ufw allow 3658/udp
sudo ufw allow from <router IP> proto udp # the router's UPnP answers
```
On Windows, in a terminal as administrator:
```
netsh advfirewall firewall add rule name="Bloodborne co-op" dir=in action=allow protocol=UDP localport=3658
```
A router whose public address is shared by many customers (CG-NAT) cannot forward ports: the
log's `UPNP: IGD found - external IP=...` should be your real public address. Tailscale works
behind CG-NAT too.
## Reading the log
Run with `BB_GPU_LOG=info` in the extra variables for the online details. In a summon:
| Line | Meaning |
|---|---|
| `Logged in npid='...'` | The shadNet login worked. |
| `summon_messenger/create` | Your sign is placed (helper). |
| `summon_messenger/get`, `sceNpMatching2CreateJoinRoom`, `summon_messenger/request` | The host found the sign, made the room and sent the summon. |
| `peer '...' endpoint unresolved` | shadNet has no address for the other player: its UDP port did not answer (the public server, above). |
| `event=0(DEAD)` | The connection gave up. |
+40
View File
@@ -0,0 +1,40 @@
# Documentation
## For players
- [COMPATIBILITY.md](COMPATIBILITY.md): which releases of Bloodborne run, and which have been
checked.
- [MODS.en.md](MODS.en.md): file mods and third-party patches.
- [ONLINE.md](ONLINE.md): online play and co-op: the account, the bells, the ports.
- [SERVER.md](SERVER.md): hosting your own co-op server (shadnet-p2p) for a group of friends.
- [TROUBLESHOOTING.md](TROUBLESHOOTING.md): common problems and what to do.
## For this fork
- [RELEASE_TEMPLATE.md](RELEASE_TEMPLATE.md): the format of every release's notes.
## bbport's development notes
Everything else here comes from [bbport](https://github.com/deadinside28/bloodborne_pc) by
deadinside28, kept as it is so that its updates merge cleanly. Many are in Russian (`.ru.md`, or
a Russian title).
- **What changed in each version:** [CHANGES_0.5.md](CHANGES_0.5.md),
[CHANGES_0.5-pre4.md](CHANGES_0.5-pre4.md), [CHANGES_0.5-pre3.md](CHANGES_0.5-pre3.md),
[CHANGES_0.5-pre2.md](CHANGES_0.5-pre2.md), [CHANGES_after_0.4.md](CHANGES_after_0.4.md),
[CHANGES_0.4.md](CHANGES_0.4.md), [CHANGES_2026-10-06.md](CHANGES_2026-10-06.md) (0.3),
[CHANGES_2026-10-03.md](CHANGES_2026-10-03.md), [CHANGES_2026-10-02.md](CHANGES_2026-10-02.md).
- **Where the port is going:** [ROADMAP.md](ROADMAP.md),
[EMULATION_REMOVAL_PLAN.ru.md](EMULATION_REMOVAL_PLAN.ru.md),
[TRANSLATOR_ARCHITECTURE.ru.md](TRANSLATOR_ARCHITECTURE.ru.md).
- **Memory and GPU commands:** [MEMORY_MODULE_PLAN.ru.md](MEMORY_MODULE_PLAN.ru.md),
[NVIDIA_MEMORY_MODEL.ru.md](NVIDIA_MEMORY_MODEL.ru.md),
[TRANSLATION_GPU_COPY_LABELS.ru.md](TRANSLATION_GPU_COPY_LABELS.ru.md),
[parallel_gpu.md](parallel_gpu.md).
- **Upscaling, TAA and motion vectors:** [upscaler.md](upscaler.md),
[DEPTH_ADAPTIVE_TAA.md](DEPTH_ADAPTIVE_TAA.md),
[TEMPORAL_REVIEW_2026-10-01.md](TEMPORAL_REVIEW_2026-10-01.md),
[motion_vectors.md](motion_vectors.md).
- **Mods, patches and TAA sharpness** (the original of MODS.en.md): [MODS.md](MODS.md).
- **The first experiments:** [DEVELOPMENT_LOG.ru.md](DEVELOPMENT_LOG.ru.md), and the session
notes in [history/](history/).
+180
View File
@@ -0,0 +1,180 @@
# Hosting your own co-op server
Bells and summons go through a shadNet server. Players who connect through shadPS4's public one
(`srv.shadps4.net`) get no co-op at the moment: it does not answer on its UDP port, so a summon
never connects ([deadinside28/bloodborne_pc#121](https://github.com/deadinside28/bloodborne_pc/issues/121)).
A group of friends can run their own server instead:
[shadnet-p2p](https://github.com/Wozzardman/shadnet-p2p) by Wozzardman, the shadNet server with
that UDP port working and a summon service of its own.
Messages, bloodstains and ghosts still come from The Hunter's Dream, whichever shadNet server you
use. Windows players of [Supermedo's port](https://github.com/Supermedo/bloodborne_pc) can join
the same server.
Tested with two players, one on this Linux port and one on Supermedo's Windows port, over
Tailscale, with the server below on a home server (Ubuntu 26.04): summons, a boss fight together
and summoning again after the helper died.
## How it fits together
- **One always-on computer runs the server:** a VPS, a home server, or one of the players' PCs
(then it has to be on while you play).
- **Everyone joins one [Tailscale](https://tailscale.com) network** (a *tailnet*): the server and
every player. Tailscale gives each computer an address starting with `100.` and encrypts the
traffic between them. This matters: shadNet's login on TCP 31313 is not encrypted, so it should
not be open to the Internet. And the games then reach each other over Tailscale too, so nobody
has to open ports on their router.
| Protocol | Port | Used for |
|---|---|---|
| TCP | 31313 | Login and matchmaking |
| UDP | 31314 | Each player's address, for the other player of a summon |
| TCP | 31315 | WebAPI and the summon service |
## 1. Tailscale
On the server and on every player's computer, install Tailscale
([download](https://tailscale.com/download); on Linux `curl -fsSL https://tailscale.com/install.sh | sh`)
and sign in:
```sh
sudo tailscale up
```
The server's owner invites the players from the
[admin console](https://login.tailscale.com/admin/users) (**Users → Invite external users**),
and each player accepts the invitation and signs in on the computer they play on. Then, on the
server:
```sh
tailscale ip -4 # the server's address, 100.x.y.z: the players need it
tailscale status # every player's computer should be listed
```
## 2. The server
### With Docker (any Linux)
This repository has a Docker image for it: [tools/shadnet-server](../tools/shadnet-server). It
builds shadnet-p2p on Debian 13, because shadnet-p2p needs Qt 6.8 or newer and some
distributions are older (Ubuntu 24.04 has Qt 6.4). It runs on any Linux with Docker, Ubuntu 24.04
included.
```sh
mkdir shadnet-server && cd shadnet-server
for f in Dockerfile entrypoint.sh; do
curl -fsSLO "https://raw.githubusercontent.com/ayozetr/bloodborne_linux/main/tools/shadnet-server/$f"
done
docker build -t bbport-shadnet .
```
Then start it, with the server's Tailscale address and a signup code of your own (letters,
digits, `-` and `_`; the players never need it, only you, to create their accounts):
```sh
docker run -d --name shadnet --restart unless-stopped --network host \
-v shadnet-data:/data \
-e SHADNET_HOST=100.x.y.z \
-e SHADNET_REGISTRATION_KEY=a-long-code-of-your-own \
bbport-shadnet
docker logs shadnet
```
The log should end with the three listeners on the Tailscale address:
```text
Unsecured TCP listener on: 100.x.y.z:31313. No encryption, use it only on trusted networks
STUN UDP listener on: 100.x.y.z:31314
WebApiServer listening on: 100.x.y.z:31315
```
`SHADNET_HOST` keeps the server off the computer's other networks. After a reboot, it waits until
Tailscale is up. The configuration (`shadnet.cfg`) and the accounts (`db/shadnet.db`) live in the
`shadnet-data` volume. To stop or update the server:
```sh
docker stop shadnet && docker rm shadnet # the volume, with the accounts, stays
docker build -t bbport-shadnet . # after downloading a newer Dockerfile
```
Then run the same `docker run` again.
### Without Docker
Follow [shadnet-p2p's README](https://github.com/Wozzardman/shadnet-p2p#readme). It needs Qt 6.8
or newer: Arch Linux and its derivatives, Debian 13, Ubuntu 26.04, Fedora 41 or newer. On Debian
and Ubuntu, install `qt6-websockets-dev` along with the packages it lists, or CMake does not find
Qt's HTTP server module (checked on Debian 13 and Ubuntu 26.04). In `build/shadnet.cfg`, set `Host` to the server's Tailscale address (or
`0.0.0.0`), `Matching2Enabled=true` and `RegistrationSecretKey` to your signup code.
### A firewall on the server
With ufw, let the tailnet in:
```sh
sudo ufw allow in on tailscale0
```
## 3. Accounts
One account per player, created on the server with the signup code. The name is 3 to 16
letters, digits, `-` or `_`:
```sh
docker exec shadnet shadnet-sample 127.0.0.1 31313 register <name> <password> <email> <signup code>
```
`127.0.0.1` works only when the server listens on every address (`SHADNET_HOST` unset or
`0.0.0.0`). With `SHADNET_HOST` set, use that address instead. The tool answers
`Account created successfully.`, or `FAILED: Unauthorized` when the code is wrong. Give each player
their own name and password.
To back up the accounts, stop the server and copy the volume's `db/shadnet.db`.
## 4. Each player's launcher
In the **Online** page:
| Setting | Value |
|---|---|
| Play online | On |
| shadNet server | **Your own server** |
| Server address | `100.x.y.z` (the port, 31313, is added) |
| WebAPI address | Empty (the server's port 31315) |
| Online ID / Password | The player's own account |
| UPnP | Off (Tailscale needs no router ports) |
Then **Test the connection**. Every line should be green, the shadNet server's UDP among them: it
shows the address the server sees for you, a `100.` one through Tailscale. A red UDP line means
summons cannot connect: check that the server is running and that its log lists the UDP listener.
Summons go through the server's own summon service: the log of a game says
`Co-op: summon signs through http://100.x.y.z:31315`.
Windows players set the same server, WebAPI and account in the Windows port's launcher.
## Seamless co-op (experimental)
shadnet-p2p can also summon between different areas: the guest is moved to the host's area. To
use it, the server and every player must have it on:
- The server: add `-e SHADNET_BLOODBORNE_SEAMLESS_COOP=1` to `docker run`, or set
`BloodborneSeamlessCoop=true` in `shadnet.cfg`. Its log then says `seamless co-op enabled`.
- Each player: **Seamless co-op (experimental)** in the launcher's Online page.
Ring the host's Beckoning Bell first, then the guest's Small Resonant Bell. Travelling together
by lantern once the session has started does not work yet.
## Troubleshooting
- **The log shows `127.0.0.1` or another address in the listeners:** check `SHADNET_HOST`, or
`Host` in the `shadnet.cfg` beside the server's executable.
- **`Waiting for 100.x.y.z` in the log:** Tailscale is not up on the server, or the address is
wrong (`tailscale ip -4`).
- **The game says it is not signed in to PlayStation Network:** a wrong name or password (code 8 in
the log), or two players using one account.
- **The test is green but summons fail:** every player's computer must be in the tailnet, not only
the server; `tailscale ping <player>` from each side. Everyone needs the game at version 1.09
and the same co-op mode.
See also [ONLINE.md](ONLINE.md) for the bells, passwords and log lines of a summon.
+62
View File
@@ -0,0 +1,62 @@
# Troubleshooting
When asking for help, attach the log: in the launcher's **Log** page, **Export log…** saves it to
a file and **Copy** puts it on the clipboard.
## The launcher rejects the game
The launcher checks the game folder before starting. What it says, and what to do:
| Message | What to do |
|---|---|
| bbport needs the 1.09 update merged into the game folder | Copy everything from the dumped 1.09 update into the game folder, replacing files (`eboot.bin` and `sce_sys` too). |
| param.sfo is from 1.09 but eboot.bin is not | Copy `eboot.bin` from the dumped 1.09 update over the old one. |
| This eboot.bin has the 60 fps patch by Lance McDonald applied | Use a clean `eboot.bin` from the 1.09 update. bbport has its own 60 FPS. |
| This is not a retail release of Bloodborne | Alpha tests and other games do not run. See [COMPATIBILITY.md](COMPATIBILITY.md). |
| eboot.bin could not be read as a decrypted PS4 executable | Dump the game and the update again. |
| The game files are damaged | The extraction tool broke compressed files (LibOrbisPkg PkgTool on .NET 6 or newer); the game would hang while loading. Extract the game and the update again with a fixed tool. |
## The game shows *New Game* instead of my save
Saves live in the data directory, and each way of running the port has its own:
- The AppImage: `~/.local/share/bbport/user/savedata/1/<title ID>/`.
- From the repository (`run.sh`): `user/savedata/1/<title ID>/` in the repository.
To move a save, close the game, back up both folders, and copy the `savedata` folder over.
## DLSS is "not supported by this GPU"
The log says why, on a line starting with `DLSS:`.
- DLSS needs a GeForce RTX (20 series or newer) and NVIDIA's own driver; it does not work with
NVK.
- The 0.4-linux.1 AppImage ships a modified copy of NVIDIA's DLSS library, which the driver
refuses (`Feature requirement query failed: 0xbad00012`): update to 0.5-linux.1 or newer.
- From the repository, DLSS needs `bash tools/build_dlss.sh` once after `build.sh`.
- If the log says `Device creation with DLSS extensions failed`, NVIDIA's CUDA/UVM
module is missing: the game then uses FSR 3.1. Load it with `sudo modprobe nvidia_uvm` (the
`nvidia-modprobe` package loads it when needed); with Secure Boot, a module signing key that
is not enrolled stops it (`Key was rejected by service`).
## Spanish shows the Latin American text (or the other way round)
The game picks a language's regional text by the dump's region. Choose it in **Settings → Game
region**: *Europe* for Spanish from Spain, *The Americas* for Latin American Spanish.
## The game crashes after playing a while, on a card with little VRAM
On a 6 GB card the texture cache can run out of video memory: the log then repeats
`Texture cache: memory pressure, ... (critical ...)`. Lower what uses VRAM: a 60 FPS limit,
a lower output resolution, lower **Model detail** in the game's *Display* settings, and close
other programs that use the GPU (browsers, video players, other games).
## Summons never connect
Run **Test the connection** in the **Online** page. A red line for the shadNet server's UDP means
the server never learns your address, and no summon can connect: shadPS4's public server does
this. Use your own server: [SERVER.md](SERVER.md).
## Other online problems
See [ONLINE.md](ONLINE.md): the account, the bells, the ports and the log lines of a summon.
+19 -36
View File
@@ -134,42 +134,6 @@ add_library(bbgpu SHARED ${VIDEO_CORE} ${RECOMPILER} ${COMMON} ${SHIM_SOURCES} $
shadps4/core/libraries/kernel/equeue.cpp ${AVPLAYER}
shadps4/core/libraries/videodec/video_utils.cpp)
add_dependencies(bbgpu host_shaders)
# bbport co-op: PS4 network and PSN libraries with the shadNet client, from shadp2p
# (github.com/Wozzardman/shadp2p, GPL-2.0), for private Bloodborne co-op servers.
find_package(Protobuf CONFIG REQUIRED)
set(SHADNET_PROTO_OUT "${CMAKE_CURRENT_BINARY_DIR}/shadnet_proto_gen")
file(MAKE_DIRECTORY "${SHADNET_PROTO_OUT}")
add_custom_command(
OUTPUT "${SHADNET_PROTO_OUT}/shadnet.pb.cc" "${SHADNET_PROTO_OUT}/shadnet.pb.h"
COMMAND protobuf::protoc "--proto_path=${CMAKE_CURRENT_SOURCE_DIR}/shadps4/shadnet"
"--cpp_out=${SHADNET_PROTO_OUT}" "${CMAKE_CURRENT_SOURCE_DIR}/shadps4/shadnet/shadnet.proto"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/shadps4/shadnet/shadnet.proto")
file(GLOB_RECURSE BBNET_SOURCES CONFIGURE_DEPENDS shadps4/core/libraries/network/*.cpp
shadps4/core/libraries/np/*.cpp shadps4/shadnet/*.cpp)
# Trophies and the system dialogs stay in the C runtime; their shadPS4 versions need the
# emulator's UI layers.
list(FILTER BBNET_SOURCES EXCLUDE REGEX
"np_trophy|trophy_ui|np_sns_facebook_dialog|np_profile_dialog/|np_commerce/")
find_package(nlohmann_json CONFIG REQUIRED)
add_library(bbnet STATIC ${BBNET_SOURCES} "${SHADNET_PROTO_OUT}/shadnet.pb.cc" bbnet/bbnet_glue.cpp)
target_include_directories(bbnet PRIVATE shim shadps4 shadps4/shadnet "${SHADNET_PROTO_OUT}"
third_party/imgui third_party/httplib)
target_link_libraries(bbnet PRIVATE nlohmann_json::nlohmann_json)
# HTTPS (the community game server only speaks TLS) and gzip replies in cpp-httplib.
find_package(OpenSSL REQUIRED)
find_package(ZLIB REQUIRED)
target_compile_definitions(bbnet PRIVATE CPPHTTPLIB_OPENSSL_SUPPORT CPPHTTPLIB_ZLIB_SUPPORT)
target_link_libraries(bbnet PRIVATE OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB)
# UPnP: opens the co-op port on the router (net_upnp.cpp).
find_path(MINIUPNPC_INCLUDE miniupnpc.h PATH_SUFFIXES miniupnpc REQUIRED)
find_library(MINIUPNPC_LIBRARY NAMES miniupnpc REQUIRED)
target_include_directories(bbnet PRIVATE "${MINIUPNPC_INCLUDE}")
target_link_libraries(bbnet PRIVATE "${MINIUPNPC_LIBRARY}")
target_compile_definitions(bbnet PRIVATE BOOST_ASIO_STANDALONE NDEBUG)
target_compile_options(bbnet PRIVATE -Wno-deprecated-declarations -Wno-missing-field-initializers)
target_link_libraries(bbnet PUBLIC Vulkan::Headers fmt::fmt Boost::headers magic_enum::magic_enum
protobuf::libprotobuf)
target_link_libraries(bbgpu PUBLIC bbnet)
# In-game settings menu: Dear ImGui (third_party/imgui, MIT) with its Vulkan backend, and an
# embedded Cyrillic font (third_party/fonts).
target_sources(bbgpu PRIVATE third_party/imgui/imgui.cpp third_party/imgui/imgui_draw.cpp
@@ -257,3 +221,22 @@ add_executable(fsr4-bench EXCLUDE_FROM_ALL tools/fsr4_bench.cpp
shadps4/video_core/renderer_vulkan/fsr411/fsr411.cpp)
target_include_directories(fsr4-bench PRIVATE shadps4/video_core/renderer_vulkan/fsr411)
target_link_libraries(fsr4-bench PRIVATE ffx-vulkan::fsr4-v07-vulkan ffx-vulkan::fsr4-v07-assets Vulkan::Vulkan)
# bbport online module (gpu/bbnet, libbbnet.so): built when its libraries are there (shell.nix);
# BB_NET=OFF leaves it out. Without it the port plays offline.
option(BB_NET "Build the online module (shadNet)" ON)
if (BB_NET)
find_package(Protobuf CONFIG QUIET)
find_package(nlohmann_json CONFIG QUIET)
find_package(OpenSSL QUIET)
find_package(ZLIB QUIET)
find_path(MINIUPNPC_INCLUDE miniupnpc.h PATH_SUFFIXES miniupnpc)
find_library(MINIUPNPC_LIBRARY NAMES miniupnpc)
if (Protobuf_FOUND AND nlohmann_json_FOUND AND OpenSSL_FOUND AND ZLIB_FOUND AND
MINIUPNPC_INCLUDE AND MINIUPNPC_LIBRARY)
add_subdirectory(bbnet)
message(STATUS "Online module: on (libbbnet.so)")
else()
message(STATUS "Online module: off (protobuf, nlohmann_json, OpenSSL, zlib or miniupnpc missing)")
endif()
endif()
+10 -2
View File
@@ -16,8 +16,6 @@ typedef struct {
} BbGpuConfig;
/* Registers kernel event queues (needed with or without graphics). */
void bbgpu_register_kernel(void);
/* Co-op: the game folder and param.sfo identity for the network and PSN libraries. */
void bbnet_configure(const char *app0, const char *serial, const char *title, const char *app_ver);
/* Creates window, Vulkan device, presenter and GPU command processor. */
int bbgpu_init(const BbGpuConfig *config);
/* Function for an imported NID ("NID#lib#mod"), or 0 when the GPU library does not provide it. */
@@ -32,6 +30,16 @@ int bbgpu_text_input_begin(const char *initial_utf8, const char *prompt_utf8);
int bbgpu_text_input_poll(char *out_utf8, uint64_t size);
/* 1 while the in-game settings menu is open: the game's pad input is held neutral. */
int bbgpu_overlay_captures_input(void);
/* A trophy the game unlocked (runtime_services.c): the overlay's notice. grade: P, G, S, B or '-';
* icon: a TROPxxx.rgba file of scripts/trophies.py (u32 width, u32 height, RGBA), or NULL. */
void bbgpu_trophy_notice(int id, char grade, const char *name_utf8, const char *icon_path);
/* Mouse look (runtime_pad.c): the window takes the mouse when it is clicked (relative mode) and
* lets it go on F1, losing focus or the menu opening. take: motion (pixels) and wheel notches
* since the last call, reset; captured: 1 while the window holds it; enable: mouse_look=0 in
* bbport.ini keeps the window from taking it. */
void bbgpu_mouse_take(double *dx, double *dy, int *wheel_up, int *wheel_down);
int bbgpu_mouse_captured(void);
void bbgpu_mouse_look_enable(int enabled);
/* Patches the loaded image before the game runs (image still writable): libGnm entry hooks. */
void bbgpu_patch_image(unsigned char *image, uint64_t size);
/* Number of symbols registered by the vendored libraries (diagnostics). */
+38
View File
@@ -0,0 +1,38 @@
# bbport online module: libbbnet.so, the PS4 network and PSN libraries with the shadNet client
# (shadp2p, a shadPS4 fork, GPL-2.0), loaded by the runtime only for online play
# (src/runtime_net.c). Its headers (include/) extend the port's shim for these libraries alone;
# everything in it is hidden and bound to itself (-Bsymbolic) except bbnet.h's two calls, so its
# copies of shadPS4's kernel shims and symbol table never meet libbbgpu's.
# Needs protobuf, nlohmann_json, OpenSSL, zlib and miniupnpc (shell.nix); without them the port
# builds without it and plays offline (gpu/CMakeLists.txt: BB_NET).
set(SHADNET_PROTO_OUT "${CMAKE_CURRENT_BINARY_DIR}/shadnet_proto_gen")
file(MAKE_DIRECTORY "${SHADNET_PROTO_OUT}")
add_custom_command(
OUTPUT "${SHADNET_PROTO_OUT}/shadnet.pb.cc" "${SHADNET_PROTO_OUT}/shadnet.pb.h"
COMMAND protobuf::protoc "--proto_path=${CMAKE_CURRENT_SOURCE_DIR}/shadps4/shadnet"
"--cpp_out=${SHADNET_PROTO_OUT}" "${CMAKE_CURRENT_SOURCE_DIR}/shadps4/shadnet/shadnet.proto"
DEPENDS "${CMAKE_CURRENT_SOURCE_DIR}/shadps4/shadnet/shadnet.proto")
file(GLOB_RECURSE BBNET_SOURCES CONFIGURE_DEPENDS shadps4/core/libraries/network/*.cpp
shadps4/core/libraries/np/*.cpp shadps4/shadnet/*.cpp)
# Trophies and the system dialogs stay in the C runtime; their shadPS4 versions need the
# emulator's UI layers.
list(FILTER BBNET_SOURCES EXCLUDE REGEX
"np_trophy|trophy_ui|np_sns_facebook_dialog|np_profile_dialog/|np_commerce/")
add_library(bbnet SHARED ${BBNET_SOURCES} "${SHADNET_PROTO_OUT}/shadnet.pb.cc" bbnet_glue.cpp)
# The module's own headers first, then the port's shim and shadPS4 (common/, logging).
target_include_directories(bbnet PRIVATE include shadps4 shadps4/shadnet "${SHADNET_PROTO_OUT}"
${CMAKE_CURRENT_SOURCE_DIR} ../shim ../shadps4 ../third_party/imgui ../third_party/httplib)
target_compile_definitions(bbnet PRIVATE BOOST_ASIO_STANDALONE NDEBUG
CPPHTTPLIB_OPENSSL_SUPPORT CPPHTTPLIB_ZLIB_SUPPORT)
target_compile_options(bbnet PRIVATE -fvisibility=hidden -fvisibility-inlines-hidden
-Wno-deprecated-declarations -Wno-missing-field-initializers)
target_link_options(bbnet PRIVATE -Wl,-Bsymbolic -Wl,--exclude-libs,ALL)
# libbbgpu (already in the process) provides shadPS4's common code: logging, threads' names.
set_target_properties(bbnet PROPERTIES BUILD_RPATH "\$ORIGIN" INSTALL_RPATH "\$ORIGIN"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}") # beside libbbgpu.so, where the runtime looks
target_link_libraries(bbnet PRIVATE bbgpu nlohmann_json::nlohmann_json protobuf::libprotobuf
OpenSSL::SSL OpenSSL::Crypto ZLIB::ZLIB "${MINIUPNPC_LIBRARY}" Vulkan::Headers fmt::fmt
Boost::headers magic_enum::magic_enum)
target_include_directories(bbnet PRIVATE "${MINIUPNPC_INCLUDE}")
+40
View File
@@ -0,0 +1,40 @@
/* bbport online module (libbbnet.so, gpu/bbnet): the PS4 network and PSN libraries with the
* shadNet client. A separate library the runtime loads only for online play (BB_ONLINE=1,
* src/runtime_net.c); offline the port never touches it, and a build without it runs offline.
* Its C++ inside is private (hidden symbols, -Bsymbolic): these two calls are all it exports. */
#ifndef BBNET_H
#define BBNET_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#define BBNET_ABI_VERSION 1
/* What the runtime gives the module: the game's identity (param.sfo, its folder for
* sce_sys/npbind.dat) and guest threads for the NP libraries' callbacks into the game. */
typedef struct BbNetHost {
uint32_t abi; /* BBNET_ABI_VERSION */
const char *app0; /* the game's folder */
const char *serial; /* TITLE_ID */
const char *title; /* TITLE */
const char *app_ver; /* APP_VER */
/* 0 or a positive errno value; entry has the System V ABI (the game's code calls it). */
int32_t (*thread_spawn)(void **thread, void *(__attribute__((sysv_abi)) *entry)(void *),
void *argument, uint64_t stack_size, const char *name);
int32_t (*thread_join)(void *thread, void **result);
} BbNetHost;
/* Registers the libraries; 0 on success, else the module cannot run (the game stays offline). */
typedef int (*BbNetInitFn)(const BbNetHost *host);
int bbnet_init(const BbNetHost *host);
/* The module's function for an imported NID ("NID#lib#mod"), or 0. */
typedef uintptr_t (*BbNetResolveFn)(const char *scoped_nid);
uintptr_t bbnet_resolve(const char *scoped_nid);
#ifdef __cplusplus
}
#endif
#endif
+52 -13
View File
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: GPL-2.0-or-later
// bbport co-op: what the network and NP libraries from shadp2p need from the rest of
// shadPS4, implemented on top of the bbport runtime, and their registration.
// bbport online module (libbbnet.so): what the network and NP libraries from shadp2p need
// from the rest of shadPS4, on top of the bbport runtime (BbNetHost), their registration and the
// module's C interface (bbnet.h). From the Linux co-op fork of bbport, which took it from the
// Windows port; the libraries are shadp2p's (a shadPS4 fork, GPL-2.0).
#include <chrono>
#include <condition_variable>
@@ -59,11 +61,12 @@
#include "core/libraries/np/np_web_api/np_web_api.h"
#include "core/libraries/np/np_web_api2/np_web_api2.h"
extern "C" {
int32_t runtime_thread_spawn(void** out, void* PS4_SYSV_ABI (*entry)(void*), void* argument,
uint64_t stack, const char* name);
int32_t runtime_thread_join_spawned(void* thread, void** result);
}
#include "bbnet.h"
namespace {
/// The runtime's side (bbnet_init).
BbNetHost g_host{};
} // namespace
// ---- Kernel ---------------------------------------------------------------------------------
@@ -278,10 +281,10 @@ int posix_pthread_create_name_np(PthreadT* thread, const PthreadAttrT* attr,
PthreadEntryFunc start, void* arg, const char* name) {
if (!thread || !start) return 22;
const u64 stack = attr && *attr ? (*attr)->stack : 0;
return runtime_thread_spawn(thread, start, arg, stack, name ? name : "np");
return g_host.thread_spawn(thread, start, arg, stack, name ? name : "np");
}
int posix_pthread_join(PthreadT thread, void** ret) {
return runtime_thread_join_spawned(thread, ret);
return g_host.thread_join(thread, ret);
}
} // namespace Libraries::Kernel
@@ -442,18 +445,52 @@ private:
};
} // namespace Core
extern "C" void bbnet_configure(const char* app0, const char* serial, const char* title,
const char* app_ver) {
namespace {
void Configure(const char* app0, const char* serial, const char* title, const char* app_ver) {
Core::Emulator::SetGame(app0, serial, title, app_ver);
const auto& ids = Common::ElfInfo::Instance().GetNpCommIds();
std::printf("Co-op: %s, NP communication id %s%s\n", serial ? serial : "?",
ids.empty() ? "missing" : ids.front().c_str(),
EmulatorSettings.IsShadNetEnabled() ? "; online play on" : "");
}
} // namespace
// ---- Registration ------------------------------------------------------------------------------
// ---- Registration and the C interface ------------------------------------------------------------
extern "C" void bbnet_register(void) {
// The module's own table (the port's libbbgpu keeps another one: this library's symbols are its
// own, -Bsymbolic).
namespace {
struct Symbol {
std::string nid;
u64 address;
};
std::vector<Symbol> g_symbols;
} // namespace
namespace Core::Loader {
void SymbolsResolver::AddSymbol(const char* nid, const char*, const char*, SymbolType, u64 address) {
g_symbols.push_back({nid, address});
}
} // namespace Core::Loader
extern "C" __attribute__((visibility("default"))) uintptr_t bbnet_resolve(const char* scoped_nid) {
const char* hash = std::strchr(scoped_nid, '#');
const size_t length = hash ? size_t(hash - scoped_nid) : std::strlen(scoped_nid);
for (const auto& symbol : g_symbols) {
if (symbol.nid.size() == length && !std::memcmp(symbol.nid.data(), scoped_nid, length)) {
return uintptr_t(symbol.address);
}
}
return 0;
}
extern "C" __attribute__((visibility("default"))) int bbnet_init(const BbNetHost* host) {
if (!host || host->abi != BBNET_ABI_VERSION || !host->thread_spawn || !host->thread_join) {
std::printf("Online: the runtime and the online module are from different versions\n");
return -1;
}
g_host = *host;
Configure(host->app0, host->serial, host->title, host->app_ver);
Core::Loader::SymbolsResolver resolver;
Core::Loader::SymbolsResolver* sym = &resolver;
Libraries::Net::RegisterLib(sym);
@@ -473,4 +510,6 @@ extern "C" void bbnet_register(void) {
Libraries::Np::NpTus::RegisterLib(sym);
Libraries::Np::NpWebApi::RegisterLib(sym);
Libraries::Np::NpWebApi2::RegisterLib(sym);
std::printf("Online: %zu network and PSN functions\n", g_symbols.size());
return 0;
}
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,93 @@
// bbport: shadPS4 settings used by the video core, read once from BB_* environment
// variables (defaults match shadPS4 except the pipeline cache, which is on).
#pragma once
#include <algorithm>
#include <atomic>
#include <cstdlib>
#include <string>
#include "common/types.h"
enum GpuReadbacksMode : int { Disabled, Relaxed, Precise };
class EmulatorSettingsImpl {
public:
static EmulatorSettingsImpl* GetInstance() { static EmulatorSettingsImpl s; return &s; }
static bool Flag(const char* name, bool fallback) {
const char* v = std::getenv(name);
return v ? (v[0] == '1' || v[0] == 'y' || v[0] == 't') : fallback;
}
static long Number(const char* name, long fallback) {
const char* v = std::getenv(name);
return v ? std::strtol(v, nullptr, 10) : fallback;
}
s32 GetGpuId() { static const auto value = s32(Number("BB_GPU_ID", -1)); return value; }
u32 GetInternalScreenWidth() { static const auto value = u32(Number("BB_INTERNAL_WIDTH", 1920)); return value; }
u32 GetInternalScreenHeight() { static const auto value = u32(Number("BB_INTERNAL_HEIGHT", 1080)); return value; }
std::string GetPresentMode() { const char* v = std::getenv("BB_PRESENT_MODE"); return v ? v : "Mailbox"; }
int GetRcasAttenuation() { static const auto value = int(Number("BB_RCAS_ATTENUATION", 250)); return value; }
// bbport: Relaxed by default: without readbacks FaceGen reads stale GPU-written vertices
// (vertex explosions); in Hunter's Nightmare it costs no measurable frame rate.
u32 GetReadbacksMode() { static const auto value = u32(Number("BB_READBACKS", GpuReadbacksMode::Relaxed)); return value; }
// bbport: uncapped presets (run.sh: BB_VBLANK_HZ=480; 0 means the same): vblank runs at
// 480 Hz, and a finished frame is presented as soon as it arrives (IsUncappedVblank), not on
// the next vblank tick (at the display rate frames alternated 10/20 ms at 100 Hz: judder; at
// 480 Hz they snap to ~2.1 ms steps). The frame rate is not limited unless BB_FPS_LIMIT
// (launcher: "FPS limit") asks for it. Other values are used as given (60/90: the
// fixed-timestep presets, flips on vblank ticks).
u32 GetVblankFrequency() {
static const u32 value = [] {
const long hz = Number("BB_VBLANK_HZ", 60);
return hz > 0 ? u32(hz) : 480u;
}();
return value;
}
/// Vblank faster than any fixed-timestep preset (above 120 Hz, or 0): flips at once.
bool IsUncappedVblank() {
static const bool value = [] {
const long hz = Number("BB_VBLANK_HZ", 60);
return hz <= 0 || hz > 120;
}();
return value;
}
/// Frames per second the present thread lets through; 0 = no limit (BB_FPS_LIMIT).
u32 GetFrameLimit() {
static const u32 value = u32(std::max(0L, Number("BB_FPS_LIMIT", 0)));
return value;
}
bool IsCopyGpuBuffers() { static const auto value = Flag("BB_COPY_GPU_BUFFERS", false); return value; }
bool IsDirectMemoryAccessEnabled() { static const auto value = Flag("BB_DIRECT_MEMORY_ACCESS", false); return value; }
bool IsDumpShaders() { static const auto value = Flag("BB_DUMP_SHADERS", false); return value; }
bool IsFsrEnabled() { static const auto value = Flag("BB_FSR1", false); return value; }
bool IsHdrAllowed() { static const auto value = Flag("BB_HDR", false); return value; }
bool IsNullGPU() { static const auto value = Flag("BB_NULL_GPU", false); return value; }
bool IsPatchShaders() { return false; }
bool IsPipelineCacheArchived() { return false; }
bool IsPipelineCacheEnabled() { static const auto value = Flag("BB_PIPELINE_CACHE", true); return value; }
bool IsRcasEnabled() { static const auto value = Flag("BB_RCAS", true); return value; }
bool IsReadbackLinearImagesEnabled() { static const auto value = Flag("BB_READBACK_LINEAR", false); return value; }
bool IsRenderdocEnabled() { return false; }
bool IsShaderCollect() { return false; }
bool IsUserfaultfdTracking() { return false; }
bool IsVkCrashDiagnosticEnabled() { return false; }
bool IsVkGuestMarkersEnabled() { static const auto value = Flag("BB_VK_MARKERS", false); return value; }
bool IsVkHostMarkersEnabled() { static const auto value = Flag("BB_VK_MARKERS", false); return value; }
bool IsVkValidationCoreEnabled() { return true; }
bool IsVkValidationEnabled() { static const auto value = Flag("BB_VK_VALIDATION", false); return value; }
bool IsVkValidationGpuEnabled() { return false; }
bool IsVkValidationSyncEnabled() { static const auto value = Flag("BB_VK_VALIDATION_SYNC", false); return value; }
// bbport co-op: online play through a shadNet server (BB_ONLINE=1, set by the launcher).
static std::string Text(const char* name, const char* fallback) {
const char* v = std::getenv(name);
return v && v[0] ? v : fallback;
}
bool IsConnectedToNetwork() { static const auto value = Flag("BB_ONLINE", false); return value; }
bool IsShadNetEnabled() { return IsConnectedToNetwork() && !shadnet_session_disabled.load(); }
void SetShadNetSessionDisabled(bool v) { shadnet_session_disabled.store(v); }
std::string GetShadNetServer() { return Text("BB_SHADNET_SERVER", "127.0.0.1:31313"); }
std::string GetShadNetWebApiServer() { return Text("BB_SHADNET_WEBAPI", "http://127.0.0.1:31315"); }
bool IsUPnPEnabled() { static const auto value = Flag("BB_UPNP", true); return value; }
private:
std::atomic<bool> shadnet_session_disabled{false};
};
#define EmulatorSettings (*EmulatorSettingsImpl::GetInstance())
File renamed without changes.
@@ -0,0 +1,15 @@
// bbport: the parts of shadPS4's kernel.h used by vendored libraries.
#pragma once
#include "common/types.h"
#include "core/libraries/kernel/orbis_error.h"
namespace Libraries::Kernel {
int* PS4_SYSV_ABI __Error();
s32 ErrnoToSceKernelError(s32 e);
struct SwVersionStruct {
u64 struct_size;
char text_representation[0x1c];
u32 hex_representation;
};
s32 PS4_SYSV_ABI sceKernelGetSystemSwVersion(SwVersionStruct* ret);
} // namespace Libraries::Kernel
@@ -0,0 +1,40 @@
// bbport: host threads that may call guest code (AvPlayer allocator callbacks).
// Each thread gets a guest TCB (GS base, TLS) from the C runtime before running.
#pragma once
#include <functional>
#include <stop_token>
#include <thread>
#include "common/types.h"
#include "core/libraries/kernel/threads/pthread.h"
extern "C" void runtime_thread_attach_host(const char* name);
namespace Libraries::Kernel {
class Thread {
public:
Thread() = default;
~Thread() { Stop(); }
void Run(std::function<void(std::stop_token)>&& func) {
thread = std::jthread([func = std::move(func)](std::stop_token stop) {
runtime_thread_attach_host("bb:hle");
func(stop);
});
}
// A thread may stop its own Thread object (AvPlayer does); it detaches instead of joining.
void Join() {
if (!thread.joinable()) return;
if (thread.get_id() == std::this_thread::get_id()) thread.detach();
else thread.join();
}
bool Joinable() const { return thread.joinable(); }
void Stop() {
if (thread.joinable()) {
thread.request_stop();
Join();
}
}
private:
std::jthread thread;
};
} // namespace Libraries::Kernel
+22
View File
@@ -0,0 +1,22 @@
// bbport: shadPS4 registers HLE functions with LIB_FUNCTION(nid, library,
// version, module, fn). Here the registrations fill a table that the C
// loader queries by NID (see bbgpu.cpp: bbgpu_resolve).
#pragma once
#include <string>
#include "common/assert.h"
#include "common/types.h"
#include "core/emulator_settings.h"
namespace Core::Loader {
enum class SymbolType { Function, Object };
class SymbolsResolver {
public:
void AddSymbol(const char* nid, const char* library, const char* module, SymbolType type, u64 address);
};
} // namespace Core::Loader
#define LIB_FUNCTION(nid, lib, libversion, mod, function) \
sym->AddSymbol(nid, lib, mod, Core::Loader::SymbolType::Function, \
reinterpret_cast<u64>(function))
#define LIB_OBJ(nid, lib, libversion, mod, obj) \
sym->AddSymbol(nid, lib, mod, Core::Loader::SymbolType::Object, reinterpret_cast<u64>(obj))
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -23,6 +23,8 @@
#include "common/logging/log.h"
#include "common/singleton.h"
#include "core/libraries/kernel/kernel.h"
#include "core/libraries/network/net_upnp.h"
#include "core/emulator_settings.h"
#include "core/libraries/network/net_util.h"
#include "net.h"
#include "net_error.h"
@@ -217,6 +219,19 @@ public:
LOG_INFO(Lib_Net,
"P2P transport ready: UDP physical_port={} (set SHADPS4_P2P_PORT to pin it)",
physical_port);
// bbport: open the port on the router (UPnP, BB_UPNP). Discovery runs in the background,
// so the mapping waits for it (issue #121: the port was never mapped, and summons from
// behind a NAT without a manual forward could not reach this player).
if (EmulatorSettings.IsUPnPEnabled()) {
const u16 port = physical_port;
std::thread([port] {
auto& upnp = UPnPClient::Instance();
upnp.Start();
if (upnp.WaitReady(10000)) {
upnp.AddMapping(port);
}
}).detach();
}
return true;
#endif
}
@@ -233,6 +248,9 @@ public:
}
CloseSocket(host_socket);
if (EmulatorSettings.IsUPnPEnabled() && physical_port != 0) {
UPnPClient::Instance().RemoveMapping(physical_port);
}
physical_port = 0;
#endif
}
Loaded 100 of 209 files, more files were not shown because too many files have changed in this diff. Show more