mirror of
https://github.com/ayozetr/bloodborne_linux.git
synced 2026-11-11 23:52:59 -10:00
Compare commits
7
Commits
0.70-linux.5
..
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1202bab21 | ||
|
|
c435733825 | ||
|
|
64acb09154 | ||
|
|
5f4ae0ac12 | ||
|
|
79b71e6b16 | ||
|
|
93a8f8e2a5 | ||
|
|
2433441711 |
No files matched your search
+4
-2
@@ -50,9 +50,10 @@ Obrikash and noelmiller. What each one did:
|
||||
- **[Classmg22](https://github.com/Classmg22)** (CLS_AMG): BBSC, Seamless Co-op.
|
||||
- **[Wozzardman](https://github.com/Wozzardman)**: the server for a group's own co-op, and BBSC's seamless summon.
|
||||
- **[droogie](https://github.com/droogie)**: The Hunter's Dream server, fast loading, and the L3 run-jump patch (Kyo's) as bbhost carries it.
|
||||
- **[Asanilo](https://github.com/Asanilo)**: two GPU fixes: work submission counts, and samplers freed after the frame that uses them.
|
||||
- **[Asanilo](https://github.com/Asanilo)**: two GPU fixes: work submission counts, and samplers freed after the frame that uses them; and the preset file's upscaler with four fields.
|
||||
- **[AlexanderDzhoganov](https://github.com/AlexanderDzhoganov)**: BBSC: the guest no longer stays a spectator after a boss wipe.
|
||||
- **[nullsumlabs](https://github.com/nullsumlabs)**: an unknown system value (sysctl) no longer stops the game.
|
||||
- **[The-Fool-cmd](https://github.com/The-Fool-cmd)**: DLSS and the launcher's folder chooser when running from source on NixOS.
|
||||
- **[fhody125-web](https://github.com/fhody125-web)**: NoDreamForHunter, the base of BBSC's game server.
|
||||
- **[MikeTat1988](https://github.com/MikeTat1988)**: Hunter's Atlas, the fullscreen in-game map.
|
||||
- **[IFreemz](https://github.com/IFreemz)**: the FSR 4 model without trails.
|
||||
@@ -98,7 +99,8 @@ Obrikash and noelmiller. What each one did:
|
||||
- **[bruxis](https://github.com/bruxis)**: the log that showed why Steam Input did not reach the game.
|
||||
- **[shauryasagar](https://github.com/shauryasagar)** and **[ZeroSTF](https://github.com/ZeroSTF)**: the Hunter's Dream going black after long sessions.
|
||||
- **[popcar2](https://github.com/popcar2)**: ideas for the launcher.
|
||||
- **[shaneo88](https://github.com/shaneo88)**: shadPS4's patch file in the patches folder.
|
||||
- **[shaneo88](https://github.com/shaneo88)**: shadPS4's patch file in the patches folder, and the camera not following the character on a controller.
|
||||
- **[brenki1](https://github.com/brenki1)**: FSR 4 stopping after lamp travels.
|
||||
- **[n3vrs0ft](https://github.com/n3vrs0ft)**: the "Transaction failed" crash on Seamless Hunt, the logs that stopped a BBSC guest from following a stranger's world, and testing BBSC 0.0.2 with a Windows player.
|
||||
- **[cappp](https://github.com/cappp)**: the "Transaction failed" crash on Seamless Hunt.
|
||||
- **[simo1730](https://github.com/simo1730)**: the Trophies page not finding the dump's files.
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
3. In the launcher, choose your **game folder**: the one with `eboot.bin` in it.
|
||||
4. Press **Play**.
|
||||
|
||||
The launcher can put itself in your applications menu or on your desktop: **Shortcut**, under
|
||||
**Add to Steam** in its settings (an AppImage manager such as Gear Lever does the same for the
|
||||
menu).
|
||||
|
||||
!!! tip "The first minutes"
|
||||
The first time, the game builds its shaders as it meets them, so it can stutter for a few
|
||||
minutes. The next sessions start with them ready.
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
From: bbport
|
||||
Subject: [PATCH] FSR 4 v07: a full external image table gives up its least used record
|
||||
|
||||
External image records are matched by view and were never removed, and the
|
||||
table holds eight. The caller makes new views whenever it recreates its
|
||||
images (an area load, a resolution change), so after a few of those every
|
||||
ffxFsr4VkSetExternalImageState failed with VK_ERROR_OUT_OF_POOL_MEMORY and
|
||||
the upscaler stopped (bbport Linux #50). The table is now kept in order of
|
||||
use, a registration moving its record to the end, and a full table drops
|
||||
the record unused the longest: the images of the frame being recorded are
|
||||
the ones registered last.
|
||||
|
||||
---
|
||||
diff --git a/src/ffx_vk_fsr4_v07.c b/src/ffx_vk_fsr4_v07.c
|
||||
--- a/src/ffx_vk_fsr4_v07.c
|
||||
+++ b/src/ffx_vk_fsr4_v07.c
|
||||
@@ -2013,14 +2013,26 @@
|
||||
return VK_ERROR_VALIDATION_FAILED_EXT;
|
||||
|
||||
FfxFsr4VkContext* c = (FfxFsr4VkContext*)iface->device;
|
||||
+ /* bbport: the table is kept in order of use, the record registered last at
|
||||
+ * its end, and a full table gives up the record unused the longest.
|
||||
+ * Records are matched by view and were never removed, and the caller makes
|
||||
+ * new views whenever it recreates its images (an area load, a resolution
|
||||
+ * change): after a few of those every registration failed with
|
||||
+ * VK_ERROR_OUT_OF_POOL_MEMORY and the upscaler stopped. The images of the
|
||||
+ * frame being recorded are the ones registered last. */
|
||||
for (uint32_t i = 0; i < c->externalImageCount; ++i) {
|
||||
if (c->externalImages[i].state.view == state->view) {
|
||||
- c->externalImages[i].state = *state;
|
||||
+ memmove(&c->externalImages[i], &c->externalImages[i + 1],
|
||||
+ (c->externalImageCount - i - 1) * sizeof(c->externalImages[0]));
|
||||
+ c->externalImages[c->externalImageCount - 1].state = *state;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
}
|
||||
- if (c->externalImageCount >= MAX_EXTERNAL_IMAGES)
|
||||
- return VK_ERROR_OUT_OF_POOL_MEMORY;
|
||||
+ if (c->externalImageCount >= MAX_EXTERNAL_IMAGES) {
|
||||
+ memmove(&c->externalImages[0], &c->externalImages[1],
|
||||
+ (MAX_EXTERNAL_IMAGES - 1) * sizeof(c->externalImages[0]));
|
||||
+ --c->externalImageCount;
|
||||
+ }
|
||||
c->externalImages[c->externalImageCount++].state = *state;
|
||||
return VK_SUCCESS;
|
||||
}
|
||||
@@ -16,3 +16,7 @@ patches here to its working tree when they are not applied yet:
|
||||
- `0004-...`: `aspectMask` in `FfxFsr4VkExternalImageState` (0 = color). The layout barriers of a
|
||||
registered external image named the color aspect, which is invalid for a depth image (the
|
||||
Linux fork's 0002).
|
||||
- `0005-...`: the FSR 4 provider's table of external images (eight, matched by view) never let
|
||||
a record go, and the port makes new views whenever it recreates its images: after a few area
|
||||
loads every registration failed with `VK_ERROR_OUT_OF_POOL_MEMORY` and FSR 4 stopped (#50).
|
||||
The table is kept in order of use and a full one drops the record unused the longest.
|
||||
@@ -210,7 +210,7 @@ bool TemporalUpscaler::OnFrameStart() {
|
||||
if (fields >= 2 && output >= 0 && output < outputs.count) {
|
||||
BbSettings::Get().output_res.store(BbSettings::PackSize(outputs.sizes[output]));
|
||||
}
|
||||
if (fields == 3 && provider >= 0 && provider < BbSettings::UpscalerCount) {
|
||||
if (fields >= 3 && provider >= 0 && provider < BbSettings::UpscalerCount) {
|
||||
BbSettings::Get().upscaler.store(provider);
|
||||
}
|
||||
std::fclose(f);
|
||||
|
||||
+70
-7
@@ -633,6 +633,13 @@ EN = {
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "Steam did not close. Close it yourself and try again",
|
||||
"Не удалось добавить игру в Steam: {}": "Couldn't add the game to Steam: {}",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne was added to your Steam library",
|
||||
'Ярлык': 'Shortcut',
|
||||
'Лаунчер в меню приложений или на рабочем столе': 'The launcher in the applications menu or on the desktop',
|
||||
'Меню приложений': 'Applications menu',
|
||||
'Рабочий стол': 'Desktop',
|
||||
'Не удалось создать ярлык: {}': 'Could not create the shortcut: {}',
|
||||
'Ярлык создан на рабочем столе': 'Shortcut created on the desktop',
|
||||
'Bloodborne добавлен в меню приложений': 'Bloodborne added to the applications menu',
|
||||
# Online page
|
||||
"Играть онлайн": "Play online",
|
||||
"Игровой сервер (сообщения, пятна крови, призраки)": "Game server (messages, bloodstains, ghosts)",
|
||||
@@ -870,6 +877,7 @@ EN = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': 'Two GPU fixes: work submission counts, and samplers freed after their frame',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': 'BBSC: the guest no longer stays a spectator after a boss wipe',
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': 'An unknown system value (sysctl) no longer stops the game',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': "DLSS and the launcher's folder chooser when running from source on NixOS",
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': 'The online play libraries and the server for your own co-op',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'The groundwork for DLSS, and the FSR 4 model without trails behind characters',
|
||||
'Апскейлер FSR 3.1': 'The FSR 3.1 upscaler',
|
||||
@@ -891,7 +899,8 @@ EN = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': 'The log that showed why Steam Input did not reach the game',
|
||||
'Чёрный Сон Охотника после долгой игры': "The Hunter's Dream going black after long sessions",
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': 'Quit to Desktop with online play on, and ideas for the launcher',
|
||||
'Файл патчей shadPS4 в папке патчей': "shadPS4's patch file in the patches folder",
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': "shadPS4's patch file in the patches folder, and the camera not following the character on a controller",
|
||||
'FSR 4, переставший работать после перемещений у ламп': 'FSR 4 stopping after lamp travels',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'The "Transaction failed" crash on Seamless Hunt',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': 'The "Transaction failed" crash on Seamless Hunt, the logs that stopped a BBSC guest from following a stranger\'s world, and testing BBSC 0.0.2 with a Windows player',
|
||||
'Страница трофеев, не находившая файлы дампа': "The Trophies page not finding the dump's files",
|
||||
@@ -1552,6 +1561,13 @@ PT_BR = {
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "O Steam não fechou. Feche-o você mesmo e tente de novo",
|
||||
"Не удалось добавить игру в Steam: {}": "Não foi possível adicionar o jogo ao Steam: {}",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne foi adicionado à sua biblioteca do Steam",
|
||||
'Ярлык': 'Atalho',
|
||||
'Лаунчер в меню приложений или на рабочем столе': 'O launcher no menu de aplicativos ou na área de trabalho',
|
||||
'Меню приложений': 'Menu de aplicativos',
|
||||
'Рабочий стол': 'Área de trabalho',
|
||||
'Не удалось создать ярлык: {}': 'Não foi possível criar o atalho: {}',
|
||||
'Ярлык создан на рабочем столе': 'Atalho criado na área de trabalho',
|
||||
'Bloodborne добавлен в меню приложений': 'Bloodborne adicionado ao menu de aplicativos',
|
||||
# Online page
|
||||
"Играть онлайн": "Jogar online",
|
||||
"Игровой сервер (сообщения, пятна крови, призраки)": "Servidor do jogo (mensagens, manchas de sangue, fantasmas)",
|
||||
@@ -1965,6 +1981,7 @@ PT_BR = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': 'Duas correções da GPU: contagem do trabalho enviado e samplers liberados após o seu quadro',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': 'BBSC: o convidado não fica mais como espectador após uma derrota no chefe',
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': 'Um valor de sistema desconhecido (sysctl) não para mais o jogo',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': 'DLSS e o seletor de pastas do launcher ao rodar do código-fonte no NixOS',
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': 'As bibliotecas do jogo online e o servidor para o seu próprio cooperativo',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'A base do suporte a DLSS e o modelo do FSR 4 sem rastros atrás dos personagens',
|
||||
'Апскейлер FSR 3.1': 'O upscaler FSR 3.1',
|
||||
@@ -1986,7 +2003,8 @@ PT_BR = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': 'O log que mostrou por que o Steam Input não chegava ao jogo',
|
||||
'Чёрный Сон Охотника после долгой игры': 'O Sonho do Caçador ficando preto depois de sessões longas',
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': '"Sair para a área de trabalho" com o jogo online e ideias para o launcher',
|
||||
'Файл патчей shadPS4 в папке патчей': 'O arquivo de patches do shadPS4 na pasta de patches',
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': 'O arquivo de patches do shadPS4 na pasta de patches e a câmera que não seguia o personagem no controle',
|
||||
'FSR 4, переставший работать после перемещений у ламп': 'O FSR 4 parando após viagens pelas lâmpadas',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'O travamento "Transaction failed" no Seamless Hunt',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': 'O crash "Transaction failed" no Seamless Hunt, os logs que fizeram o convidado do BBSC parar de seguir o mundo de um estranho e os testes do BBSC 0.0.2 com um jogador no Windows',
|
||||
'Страница трофеев, не находившая файлы дампа': 'A página de troféus que não encontrava os arquivos do dump',
|
||||
@@ -2652,6 +2670,13 @@ ES = {
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "Steam no se ha cerrado. Ciérralo tú y vuelve a intentarlo",
|
||||
"Не удалось добавить игру в Steam: {}": "No se pudo añadir el juego a Steam: {}",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne se ha añadido a tu biblioteca de Steam",
|
||||
'Ярлык': 'Acceso directo',
|
||||
'Лаунчер в меню приложений или на рабочем столе': 'El launcher en el menú de aplicaciones o en el escritorio',
|
||||
'Меню приложений': 'Menú de aplicaciones',
|
||||
'Рабочий стол': 'Escritorio',
|
||||
'Не удалось создать ярлык: {}': 'No se pudo crear el acceso directo: {}',
|
||||
'Ярлык создан на рабочем столе': 'Acceso directo creado en el escritorio',
|
||||
'Bloodborne добавлен в меню приложений': 'Bloodborne añadido al menú de aplicaciones',
|
||||
# Online page
|
||||
"Играть онлайн": "Jugar online",
|
||||
"Игровой сервер (сообщения, пятна крови, призраки)": "Servidor del juego (mensajes, manchas de sangre, fantasmas)",
|
||||
@@ -2975,6 +3000,7 @@ ES = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': 'Dos arreglos de la GPU: el recuento del trabajo enviado y los samplers liberados tras su fotograma',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': 'BBSC: el invitado ya no se queda de espectador tras caer todos ante un jefe',
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': 'Un valor del sistema desconocido (sysctl) ya no detiene el juego',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': 'DLSS y el selector de carpetas del launcher al ejecutar desde el código en NixOS',
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': 'Las librerías del juego online y el servidor para el cooperativo propio',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'La base del soporte de DLSS y el modelo de FSR 4 sin estelas tras los personajes',
|
||||
'Апскейлер FSR 3.1': 'El escalado FSR 3.1',
|
||||
@@ -2996,7 +3022,8 @@ ES = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': 'El log que mostró por qué Steam Input no llegaba al juego',
|
||||
'Чёрный Сон Охотника после долгой игры': 'El Sueño del Cazador en negro tras sesiones largas',
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': '«Salir al escritorio» con el juego online e ideas para el launcher',
|
||||
'Файл патчей shadPS4 в папке патчей': 'El archivo de parches de shadPS4 en la carpeta de parches',
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': 'El archivo de parches de shadPS4 en la carpeta de parches y la cámara que no seguía al personaje con mando',
|
||||
'FSR 4, переставший работать после перемещений у ламп': 'FSR 4 dejando de funcionar tras viajar entre lámparas',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'El cierre «Transaction failed» en Seamless Hunt',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': 'El cierre «Transaction failed» en Seamless Hunt, los registros que hicieron que el invitado de BBSC dejara de seguir el mundo de un desconocido y las pruebas de BBSC 0.0.2 con un jugador en Windows',
|
||||
'Страница трофеев, не находившая файлы дампа': 'La página de trofeos que no encontraba los archivos del volcado',
|
||||
@@ -3662,6 +3689,13 @@ IT = {
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "Steam non si è chiuso. Chiudilo tu e riprova",
|
||||
"Не удалось добавить игру в Steam: {}": "Impossibile aggiungere il gioco a Steam: {}",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne è stato aggiunto alla tua libreria di Steam",
|
||||
'Ярлык': 'Collegamento',
|
||||
'Лаунчер в меню приложений или на рабочем столе': 'Il launcher nel menu delle applicazioni o sul desktop',
|
||||
'Меню приложений': 'Menu applicazioni',
|
||||
'Рабочий стол': 'Desktop',
|
||||
'Не удалось создать ярлык: {}': 'Impossibile creare il collegamento: {}',
|
||||
'Ярлык создан на рабочем столе': 'Collegamento creato sul desktop',
|
||||
'Bloodborne добавлен в меню приложений': 'Bloodborne aggiunto al menu delle applicazioni',
|
||||
# Online page
|
||||
"Играть онлайн": "Gioca online",
|
||||
"Игровой сервер (сообщения, пятна крови, призраки)": "Server di gioco (messaggi, macchie di sangue, fantasmi)",
|
||||
@@ -3985,6 +4019,7 @@ IT = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': 'Due correzioni della GPU: il conteggio del lavoro inviato e i sampler liberati dopo il loro fotogramma',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': "BBSC: l'ospite non resta più spettatore dopo una sconfitta contro un boss",
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': 'Un valore di sistema sconosciuto (sysctl) non ferma più il gioco',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': 'DLSS e la scelta della cartella nel launcher eseguendo dai sorgenti su NixOS',
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': 'Le librerie del gioco online e il server per la propria cooperativa',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'La base del supporto DLSS e il modello FSR 4 senza scie dietro i personaggi',
|
||||
'Апскейлер FSR 3.1': 'L’upscaler FSR 3.1',
|
||||
@@ -4006,7 +4041,8 @@ IT = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': 'Il log che ha mostrato perché Steam Input non arrivava al gioco',
|
||||
'Чёрный Сон Охотника после долгой игры': 'Il Sogno del Cacciatore nero dopo sessioni lunghe',
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': '"Esci al desktop" con il gioco online e idee per il launcher',
|
||||
'Файл патчей shadPS4 в папке патчей': 'Il file di patch di shadPS4 nella cartella delle patch',
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': 'Il file delle patch di shadPS4 nella cartella delle patch e la telecamera che non seguiva il personaggio col controller',
|
||||
'FSR 4, переставший работать после перемещений у ламп': 'FSR 4 che smetteva di funzionare dopo i viaggi tra le lanterne',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'La chiusura "Transaction failed" su Seamless Hunt',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': "Il crash «Transaction failed» su Seamless Hunt, i log che hanno fatto smettere all'ospite di BBSC di seguire il mondo di uno sconosciuto e i test di BBSC 0.0.2 con un giocatore su Windows",
|
||||
'Страница трофеев, не находившая файлы дампа': 'La pagina dei trofei che non trovava i file del dump',
|
||||
@@ -4672,6 +4708,13 @@ FR = {
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "Steam ne s'est pas fermé. Fermez-le vous-même et réessayez",
|
||||
"Не удалось добавить игру в Steam: {}": "Impossible d'ajouter le jeu à Steam : {}",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne a été ajouté à votre bibliothèque Steam",
|
||||
'Ярлык': 'Raccourci',
|
||||
'Лаунчер в меню приложений или на рабочем столе': 'Le launcher dans le menu des applications ou sur le bureau',
|
||||
'Меню приложений': 'Menu des applications',
|
||||
'Рабочий стол': 'Bureau',
|
||||
'Не удалось создать ярлык: {}': 'Impossible de créer le raccourci : {}',
|
||||
'Ярлык создан на рабочем столе': 'Raccourci créé sur le bureau',
|
||||
'Bloodborne добавлен в меню приложений': 'Bloodborne ajouté au menu des applications',
|
||||
# Online page
|
||||
"Играть онлайн": "Jouer en ligne",
|
||||
"Игровой сервер (сообщения, пятна крови, призраки)": "Serveur de jeu (messages, taches de sang, fantômes)",
|
||||
@@ -4995,6 +5038,7 @@ FR = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': 'Deux correctifs GPU : le décompte du travail soumis et les samplers libérés après leur image',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': "BBSC : l'invité ne reste plus spectateur après une défaite face à un boss",
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': 'Une valeur système inconnue (sysctl) n’arrête plus le jeu',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': 'DLSS et le sélecteur de dossier du launcher en lançant depuis les sources sous NixOS',
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': 'Les bibliothèques du jeu en ligne et le serveur pour votre propre coopération',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'La base de la prise en charge de DLSS et le modèle FSR 4 sans traînées derrière les personnages',
|
||||
'Апскейлер FSR 3.1': 'L’upscaler FSR 3.1',
|
||||
@@ -5016,7 +5060,8 @@ FR = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': "Le journal qui a montré pourquoi Steam Input n'atteignait pas le jeu",
|
||||
'Чёрный Сон Охотника после долгой игры': 'Le Rêve du chasseur noir après de longues sessions',
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': '« Quitter vers le bureau » en jeu en ligne, et des idées pour le lanceur',
|
||||
'Файл патчей shadPS4 в папке патчей': 'Le fichier de patchs de shadPS4 dans le dossier des patchs',
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': 'Le fichier de patchs de shadPS4 dans le dossier des patchs, et la caméra qui ne suivait pas le personnage à la manette',
|
||||
'FSR 4, переставший работать после перемещений у ламп': 'FSR 4 qui cessait de fonctionner après des voyages entre lanternes',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'Le plantage « Transaction failed » sur Seamless Hunt',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': "Le plantage « Transaction failed » sur Seamless Hunt, les journaux qui ont empêché l'invité de BBSC de suivre le monde d'un inconnu, et les tests de BBSC 0.0.2 avec un joueur sous Windows",
|
||||
'Страница трофеев, не находившая файлы дампа': 'La page des trophées qui ne trouvait pas les fichiers du dump',
|
||||
@@ -5682,6 +5727,13 @@ DE = {
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "Steam wurde nicht geschlossen. Schließe es selbst und versuche es erneut",
|
||||
"Не удалось добавить игру в Steam: {}": "Spiel konnte nicht zu Steam hinzugefügt werden: {}",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne wurde deiner Steam-Bibliothek hinzugefügt",
|
||||
'Ярлык': 'Verknüpfung',
|
||||
'Лаунчер в меню приложений или на рабочем столе': 'Der Launcher im Anwendungsmenü oder auf dem Desktop',
|
||||
'Меню приложений': 'Anwendungsmenü',
|
||||
'Рабочий стол': 'Desktop',
|
||||
'Не удалось создать ярлык: {}': 'Die Verknüpfung konnte nicht erstellt werden: {}',
|
||||
'Ярлык создан на рабочем столе': 'Verknüpfung auf dem Desktop erstellt',
|
||||
'Bloodborne добавлен в меню приложений': 'Bloodborne zum Anwendungsmenü hinzugefügt',
|
||||
# Online page
|
||||
"Играть онлайн": "Online spielen",
|
||||
"Игровой сервер (сообщения, пятна крови, призраки)": "Spielserver (Nachrichten, Blutflecken, Geister)",
|
||||
@@ -6005,6 +6057,7 @@ DE = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': 'Zwei GPU-Fehlerbehebungen: die Zählung der übermittelten Arbeit und Sampler, die nach ihrem Frame freigegeben werden',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': 'BBSC: der Gast bleibt nach einer Niederlage gegen einen Boss nicht mehr Zuschauer',
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': 'Ein unbekannter Systemwert (sysctl) hält das Spiel nicht mehr an',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': 'DLSS und die Ordnerauswahl des Launchers beim Start aus dem Quellcode unter NixOS',
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': 'Die Bibliotheken für das Online-Spiel und der Server für den eigenen Koop',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'Die Grundlage für DLSS und das FSR-4-Modell ohne Schlieren hinter Figuren',
|
||||
'Апскейлер FSR 3.1': 'Der FSR-3.1-Upscaler',
|
||||
@@ -6026,7 +6079,8 @@ DE = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': 'Das Log, das zeigte, warum Steam Input das Spiel nicht erreichte',
|
||||
'Чёрный Сон Охотника после долгой игры': 'Der schwarze Traum des Jägers nach langen Sitzungen',
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': '„Zum Desktop beenden“ beim Onlinespiel und Ideen für den Launcher',
|
||||
'Файл патчей shadPS4 в папке патчей': 'Die Patch-Datei von shadPS4 im Patch-Ordner',
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': 'Die Patch-Datei von shadPS4 im Patch-Ordner und die Kamera, die der Figur mit Controller nicht folgte',
|
||||
'FSR 4, переставший работать после перемещений у ламп': 'FSR 4, das nach Laternenreisen ausfiel',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'Der Absturz „Transaction failed“ auf Seamless Hunt',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': 'Der Absturz „Transaction failed“ auf Seamless Hunt, die Logs, durch die ein BBSC-Gast nicht mehr der Welt eines Fremden folgt, und Tests von BBSC 0.0.2 mit einem Windows-Spieler',
|
||||
'Страница трофеев, не находившая файлы дампа': 'Die Trophäenseite, die die Dateien des Dumps nicht fand',
|
||||
@@ -6843,6 +6897,13 @@ ZH_CN = {
|
||||
", основной": ",主显示器",
|
||||
"0: случайный при каждом запуске. Закрепите его, чтобы открыть в брандмауэре или на роутере вручную": "0:每次使用随机端口。如需在防火墙或路由器上手动开放,请固定一个端口",
|
||||
"Bloodborne добавлен в библиотеку Steam": "Bloodborne 已添加到你的 Steam 库",
|
||||
'Ярлык': '快捷方式',
|
||||
'Лаунчер в меню приложений или на рабочем столе': '在应用菜单或桌面上放置启动器',
|
||||
'Меню приложений': '应用菜单',
|
||||
'Рабочий стол': '桌面',
|
||||
'Не удалось создать ярлык: {}': '无法创建快捷方式:{}',
|
||||
'Ярлык создан на рабочем столе': '已在桌面创建快捷方式',
|
||||
'Bloodborne добавлен в меню приложений': '已将 Bloodborne 添加到应用菜单',
|
||||
"Online ID — это имя учётной записи (NPID), зарегистрированное на сервере, а не адрес email": "Online ID 是你在服务器上注册的账号名(NPID),而不是邮箱地址",
|
||||
"PlayStation (оригинал)": "PlayStation(原版)",
|
||||
"Steam не закрылся. Закройте его сами и попробуйте ещё раз": "Steam 没有关闭。请手动关闭后重试",
|
||||
@@ -6984,6 +7045,7 @@ ZH_CN = {
|
||||
'Два исправления GPU: счётчики отправленной работы и сэмплеры, освобождаемые после их кадра': '两项 GPU 修复:已提交工作的计数,以及在其帧结束后才释放的采样器',
|
||||
'BBSC: гость больше не остаётся зрителем после гибели группы у босса': 'BBSC:首领战全灭后,客人不再一直处于观战状态',
|
||||
'Неизвестный системный параметр (sysctl) больше не останавливает игру': '未知的系统值(sysctl)不再导致游戏停止',
|
||||
'DLSS и выбор папки в лаунчере при запуске из исходников на NixOS': '在 NixOS 上从源码运行时的 DLSS 与启动器文件夹选择',
|
||||
'Сетевые библиотеки игры по сети и сервер для своего кооператива': '联机库与自建合作服务器',
|
||||
'Основа поддержки DLSS и модель FSR 4 без шлейфов за персонажами': 'DLSS 支持的基础,以及角色身后无拖影的 FSR 4 模型',
|
||||
'Апскейлер FSR 3.1': 'FSR 3.1 超分辨率',
|
||||
@@ -7005,7 +7067,8 @@ ZH_CN = {
|
||||
'Журнал, показавший, почему Steam Input не доходил до игры': '指出 Steam Input 为何无法传到游戏的日志',
|
||||
'Чёрный Сон Охотника после долгой игры': '长时间游玩后猎人梦境变黑',
|
||||
'«Выход на рабочий стол» при игре по сети и идеи для лаунчера': '联机时的“退出到桌面”以及对启动器的建议',
|
||||
'Файл патчей shadPS4 в папке патчей': '补丁文件夹中的 shadPS4 补丁文件',
|
||||
'Файл патчей shadPS4 в папке патчей и камера, которая не следовала за персонажем с геймпадом': '补丁文件夹中的 shadPS4 补丁文件,以及使用手柄时镜头不跟随角色的问题',
|
||||
'FSR 4, переставший работать после перемещений у ламп': '在灯之间传送后 FSR 4 停止工作的问题',
|
||||
'Вылет «Transaction failed» на Seamless Hunt': 'Seamless Hunt 上的“Transaction failed”崩溃',
|
||||
'Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с игроком на Windows': 'Seamless Hunt 上的“Transaction failed”崩溃、让 BBSC 访客不再跟随陌生人世界的日志,以及与 Windows 玩家一起测试 BBSC 0.0.2',
|
||||
'Страница трофеев, не находившая файлы дампа': '找不到转储文件的奖杯页面',
|
||||
|
||||
@@ -28,6 +28,7 @@ from bbport_i18n import language, set_language, system_game_language, tr
|
||||
import bbport_cache
|
||||
import bbport_atlas_maps
|
||||
import bbport_coop
|
||||
import bbport_shortcut
|
||||
import bbport_steam
|
||||
import bbport_update
|
||||
|
||||
@@ -1042,6 +1043,7 @@ THANKS = (
|
||||
"освобождаемые после их кадра"),
|
||||
_github("AlexanderDzhoganov", "BBSC: гость больше не остаётся зрителем после гибели группы у босса"),
|
||||
_github("nullsumlabs", "Неизвестный системный параметр (sysctl) больше не останавливает игру"),
|
||||
_github("The-Fool-cmd", "DLSS и выбор папки в лаунчере при запуске из исходников на NixOS"),
|
||||
_github("Wozzardman", "Сервер для своего кооператива и бесшовный призыв BBSC"),
|
||||
_github("IFreemz", "Модель FSR 4 без шлейфов за персонажами"),
|
||||
_github("FireBurn", "Апскейлер FSR 3.1"),
|
||||
@@ -1078,7 +1080,9 @@ THANKS = (
|
||||
_github("shauryasagar", "Чёрный Сон Охотника после долгой игры"),
|
||||
_github("ZeroSTF", "Чёрный Сон Охотника после долгой игры"),
|
||||
_github("popcar2", "Идеи для лаунчера"),
|
||||
_github("shaneo88", "Файл патчей shadPS4 в папке патчей"),
|
||||
_github("shaneo88", "Файл патчей shadPS4 в папке патчей и камера, которая не следовала за "
|
||||
"персонажем с геймпадом"),
|
||||
_github("brenki1", "FSR 4, переставший работать после перемещений у ламп"),
|
||||
_github("n3vrs0ft", "Вылет «Transaction failed» на Seamless Hunt, журналы, по которым гость "
|
||||
"BBSC перестал следовать за чужим хозяином, и проверки BBSC 0.0.2 с "
|
||||
"игроком на Windows"),
|
||||
@@ -1355,6 +1359,16 @@ class LauncherWindow(Adw.ApplicationWindow):
|
||||
steam.add_prefix(themed_icon("steam-symbolic"))
|
||||
steam.add_suffix(steam_button)
|
||||
game.add(steam)
|
||||
# A menu entry (and one on the desktop) for the AppImage or this checkout: an AppImage
|
||||
# has none unless an AppImage manager makes it (bbport_shortcut.py).
|
||||
shortcut = Adw.ActionRow(title=tr("Ярлык"),
|
||||
subtitle=tr("Лаунчер в меню приложений или на рабочем столе"))
|
||||
shortcut.add_prefix(themed_icon("application-x-executable-symbolic"))
|
||||
for label, where in ((tr("Меню приложений"), "menu"), (tr("Рабочий стол"), "desktop")):
|
||||
button = Gtk.Button(label=label, valign=Gtk.Align.CENTER)
|
||||
button.connect("clicked", self.on_create_shortcut, where)
|
||||
shortcut.add_suffix(button)
|
||||
game.add(shortcut)
|
||||
self.steam_overlay_row = Adw.SwitchRow(
|
||||
title=tr("Оверлей Steam"),
|
||||
subtitle=tr("Кнопка Steam, счётчик FPS и снимки экрана Steam, когда игра запущена из Steam"),
|
||||
@@ -2630,6 +2644,29 @@ class LauncherWindow(Adw.ApplicationWindow):
|
||||
return False
|
||||
GLib.timeout_add(500, poll)
|
||||
|
||||
def on_create_shortcut(self, _button, where):
|
||||
appimage = os.environ.get("APPIMAGE")
|
||||
target = appimage or str(PORT_DIR / "launcher" / "bb-launcher.sh")
|
||||
icon = PORT_DIR / "launcher" / "bloodborne.png"
|
||||
if appimage:
|
||||
# The AppImage's mount is gone once it closes: the icon is kept in the data folder.
|
||||
try:
|
||||
kept = DATA_DIR / "bloodborne.png"
|
||||
kept.write_bytes(icon.read_bytes())
|
||||
icon = kept
|
||||
except OSError:
|
||||
pass
|
||||
desktop = where == "desktop"
|
||||
folder = bbport_shortcut.desktop_dir() if desktop else bbport_shortcut.applications_dir()
|
||||
try:
|
||||
path = bbport_shortcut.write_entry(folder, target, str(icon), trusted=desktop)
|
||||
except OSError as error:
|
||||
self.alert(tr("Ярлык"), tr("Не удалось создать ярлык: {}").format(error))
|
||||
return
|
||||
message = tr("Ярлык создан на рабочем столе") if desktop else tr("Bloodborne добавлен в меню приложений")
|
||||
print(f"Launcher: shortcut written to {path}")
|
||||
self.toasts.add_toast(Adw.Toast(title=message, timeout=6))
|
||||
|
||||
def add_to_steam(self, steam, configs, restart):
|
||||
# Packaged: the AppImage itself; from a checkout: the launcher script.
|
||||
appimage = os.environ.get("APPIMAGE")
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 bbport contributors
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
"""A desktop entry for the launcher: in the applications menu and on the desktop.
|
||||
|
||||
The AppImage has no menu entry of its own unless an AppImage manager (Gear Lever, AppImageLauncher)
|
||||
makes one, and a checkout has launcher/install-desktop.sh. The launcher's "Create shortcut" writes
|
||||
one for whichever it is: the AppImage itself, or the checkout's bb-launcher.sh.
|
||||
"""
|
||||
import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
ENTRY_NAME = "io.github.ayozetr.bloodborne_linux.desktop"
|
||||
|
||||
|
||||
def exec_quote(path):
|
||||
"""`path` as one Exec argument (Desktop Entry Specification: double quotes, with ", `, $ and \\
|
||||
escaped)."""
|
||||
escaped = "".join("\\" + c if c in '"`$\\' else c for c in str(path))
|
||||
return f'"{escaped}"'
|
||||
|
||||
|
||||
def entry_text(target, icon):
|
||||
"""The desktop entry that starts `target` (the AppImage or bb-launcher.sh) with `icon`."""
|
||||
return ("[Desktop Entry]\n"
|
||||
"Type=Application\n"
|
||||
"Name=Bloodborne (bbport)\n"
|
||||
"Comment=Native Linux port launcher for your own copy of Bloodborne\n"
|
||||
f"Exec={exec_quote(target)}\n"
|
||||
f"Icon={icon}\n"
|
||||
"Terminal=false\n"
|
||||
"Categories=Game;\n"
|
||||
"StartupWMClass=io.github.bbport.Launcher\n")
|
||||
|
||||
|
||||
def applications_dir(env=os.environ):
|
||||
"""Where the user's own menu entries go ($XDG_DATA_HOME/applications)."""
|
||||
data = env.get("XDG_DATA_HOME") or str(Path.home() / ".local" / "share")
|
||||
return Path(data) / "applications"
|
||||
|
||||
|
||||
def desktop_dir():
|
||||
"""The desktop folder (xdg-user-dir DESKTOP: "Escritorio", "Bureau"...), else ~/Desktop."""
|
||||
try:
|
||||
out = subprocess.run(["xdg-user-dir", "DESKTOP"], capture_output=True, text=True,
|
||||
timeout=5).stdout.strip()
|
||||
if out and Path(out).is_dir() and Path(out) != Path.home():
|
||||
return Path(out)
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
pass
|
||||
return Path.home() / "Desktop"
|
||||
|
||||
|
||||
def write_entry(folder, target, icon, trusted=False):
|
||||
"""Writes the entry into `folder` and returns its path. On the desktop (`trusted`) it is made
|
||||
executable and marked trusted for GNOME's file manager, which otherwise will not start it."""
|
||||
folder.mkdir(parents=True, exist_ok=True)
|
||||
path = folder / ENTRY_NAME
|
||||
path.write_text(entry_text(target, icon), encoding="utf-8")
|
||||
path.chmod(0o755 if trusted else 0o644)
|
||||
if trusted:
|
||||
try:
|
||||
subprocess.run(["gio", "set", str(path), "metadata::trusted", "true"],
|
||||
capture_output=True, timeout=5)
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
pass
|
||||
else:
|
||||
try:
|
||||
subprocess.run(["update-desktop-database", str(folder)], capture_output=True, timeout=10)
|
||||
except (OSError, subprocess.SubprocessError):
|
||||
pass
|
||||
return path
|
||||
@@ -14,7 +14,7 @@ import re
|
||||
import tempfile
|
||||
import urllib.request
|
||||
|
||||
VERSION = "0.70-linux.5"
|
||||
VERSION = "0.70-linux.6"
|
||||
|
||||
|
||||
def _build():
|
||||
|
||||
@@ -5,4 +5,9 @@ pkgs.mkShell {
|
||||
(python3.withPackages (ps: [ ps.pygobject3 ]))
|
||||
gtk4 libadwaita gobject-introspection
|
||||
];
|
||||
# The same data directories packaging/default.nix gives the packaged launcher: icons for hosts
|
||||
# without an Adwaita theme, and GTK4's schemas, which the file chooser aborts without.
|
||||
shellHook = ''
|
||||
export XDG_DATA_DIRS=${pkgs.adwaita-icon-theme}/share:${pkgs.hicolor-icon-theme}/share:${pkgs.gtk4}/share/gsettings-schemas/${pkgs.gtk4.name}''${XDG_DATA_DIRS:+:$XDG_DATA_DIRS}
|
||||
'';
|
||||
}
|
||||
@@ -26,4 +26,10 @@ pkgs.mkShell {
|
||||
# Online module (gpu/bbnet): shadNet client, HTTPS, UPnP
|
||||
protobuf nlohmann_json openssl zlib miniupnpc
|
||||
];
|
||||
# NixOS keeps the driver's libraries in /run/opengl-driver/lib, where the DLSS bridge's dlopen of
|
||||
# libnvidia-ngx.so.1 does not look (the AppImage links them in: launcher/bbport_vulkan.py).
|
||||
# Only driver libraries live there, so nothing the shell provides is replaced.
|
||||
shellHook = ''
|
||||
export LD_LIBRARY_PATH=''${LD_LIBRARY_PATH:+$LD_LIBRARY_PATH:}${pkgs.addDriverRunpath.driverLink}/lib
|
||||
'';
|
||||
}
|
||||
@@ -559,7 +559,10 @@ static uint8_t look_axis(float value, uint8_t stick, int deadzone) {
|
||||
/* While the mouse turns the camera, the game's own camera auto-rotation (it swings the camera
|
||||
* behind the character on strafes, made for a stick) fights it: its three stores (1.09) are NOPs
|
||||
* then, put back when the mouse is let go (#352). Only where the bytes are the game's own.
|
||||
* BB_MOUSE_AUTO_ROTATE=1: left as the game does it. */
|
||||
* BB_MOUSE_AUTO_ROTATE=1: left as the game does it. Not while the gamepad is what is being played
|
||||
* with (gamepad_playing, sample.c): the window holds the mouse whenever it has the focus, and a
|
||||
* player on a controller lost the camera following the character (#51). */
|
||||
static int gamepad_playing; /* the gamepad was used last, not the keyboard or the mouse */
|
||||
static void mouse_auto_rotation_hold(int hold) {
|
||||
static int held=-1, off=-1;
|
||||
if (off<0) { const char *e=bb_env("BB_MOUSE_AUTO_ROTATE"); off=e && e[0]=='1'; }
|
||||
@@ -588,7 +591,7 @@ static void mouse_auto_rotation_hold(int hold) {
|
||||
held=hold;
|
||||
}
|
||||
static void apply_mouse_look(PadData *d, double dx, double dy, uint64_t now, int captured) {
|
||||
mouse_auto_rotation_hold(mouse_look && captured && !bbgpu_free_camera());
|
||||
mouse_auto_rotation_hold(mouse_look && captured && !gamepad_playing && !bbgpu_free_camera());
|
||||
/* The free camera (patch) takes the mouse through the right stick below. */
|
||||
if (captured && (dx!=0 || dy!=0) && !bbgpu_free_camera()) {
|
||||
const float k=MOUSE_RAD_PER_PIXEL*mouse_sensitivity;
|
||||
|
||||
@@ -190,6 +190,8 @@ static void sample_host(PadData *d) {
|
||||
(mouse_buttons!=0));
|
||||
for (int i=0;i<IN_COUNT && !keyboard_active;++i) keyboard_active=key_down(k,i);
|
||||
prompt_note(g,pad_active,keyboard_active);
|
||||
if (keyboard_active) gamepad_playing=0;
|
||||
else if (pad_active) gamepad_playing=1;
|
||||
apply_keyboard(d,k); /* the bound mouse buttons too */
|
||||
video_skip(d,k);
|
||||
if (motion_on()) {
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 bbport contributors
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
"""Exercise the production preset-file reader without a Vulkan device.
|
||||
|
||||
Compile the unchanged OnFrameStart polling/reading block with the real settings
|
||||
implementation. Only the remaining frame/GPU work is omitted from the harness.
|
||||
"""
|
||||
import os
|
||||
from pathlib import Path
|
||||
import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import tempfile
|
||||
import unittest
|
||||
|
||||
from paths import ROOT
|
||||
|
||||
|
||||
class PresetFileTests(unittest.TestCase):
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
compiler = shlex.split(os.environ.get('CXX', 'c++'))
|
||||
if not compiler or not shutil.which(compiler[0]):
|
||||
raise unittest.SkipTest('a C++23 compiler is required')
|
||||
cls.tmp = tempfile.TemporaryDirectory()
|
||||
cls.addClassCleanup(cls.tmp.cleanup)
|
||||
cls.folder = Path(cls.tmp.name)
|
||||
source = (ROOT / 'gpu/upscale/vk_temporal_upscaler.cpp').read_text(encoding='utf-8')
|
||||
start = source.index('static const char* preset_file',
|
||||
source.index('bool TemporalUpscaler::OnFrameStart() {'))
|
||||
end = source.index('const auto& settings = BbSettings::Get();', start)
|
||||
reader = source[start:end]
|
||||
harness = cls.folder / 'preset_file.cpp'
|
||||
harness.write_text('''#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include "shim/bb_env.h"
|
||||
#include "shim/bbport_settings.h"
|
||||
|
||||
void Poll() {
|
||||
static unsigned preset_file_frames = 0;
|
||||
''' + reader + '''}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
auto& s = BbSettings::Get();
|
||||
s.preset = BbSettings::Balanced;
|
||||
s.upscaler = BbSettings::UpscalerDlss;
|
||||
s.aspect = BbSettings::Aspect16x9;
|
||||
s.output_res = BbSettings::PackSize({1920, 1080});
|
||||
const int frames = argc > 1 ? std::atoi(argv[1]) : 64;
|
||||
for (int i = 0; i < frames; ++i) Poll();
|
||||
const auto output = BbSettings::UnpackSize(s.output_res.load());
|
||||
std::printf("%d %d %d %d %d\\n", s.preset.load(), s.upscaler.load(),
|
||||
s.aspect.load(), output.width, output.height);
|
||||
std::fprintf(stderr, "%d\\n", int(BbSettings::UpscalerCount));
|
||||
}
|
||||
''', encoding='utf-8')
|
||||
cls.exe = cls.folder / 'preset-file-test'
|
||||
result = subprocess.run(compiler + ['-std=c++23', '-Wall', '-Wextra', '-Werror',
|
||||
'-I', str(ROOT / 'gpu'), str(harness),
|
||||
str(ROOT / 'gpu/shim/bbport_settings.cpp'),
|
||||
'-o', str(cls.exe)], capture_output=True, text=True, timeout=60)
|
||||
if result.returncode:
|
||||
raise RuntimeError(result.stdout + result.stderr)
|
||||
# The provider list is the real one, not a copy: a provider added later is covered too.
|
||||
probe = subprocess.run([str(cls.exe), '0'], capture_output=True, text=True, check=True)
|
||||
cls.providers = int(probe.stderr)
|
||||
|
||||
def read(self, text, frames=64):
|
||||
request = self.folder / 'request.txt'
|
||||
if text is None:
|
||||
request.unlink(missing_ok=True)
|
||||
else:
|
||||
request.write_text(text, encoding='utf-8')
|
||||
env = dict(os.environ, BB_PRESET_FILE=str(request))
|
||||
result = subprocess.run([str(self.exe), str(frames)], env=env,
|
||||
capture_output=True, text=True, timeout=5, check=True)
|
||||
return tuple(map(int, result.stdout.split()))
|
||||
|
||||
def test_four_fields_apply_provider_and_aspect(self):
|
||||
self.assertEqual(self.read('1 0 0 3'), (1, 0, 3, 640, 360))
|
||||
|
||||
def test_three_and_four_fields_accept_every_provider(self):
|
||||
for provider in range(self.providers):
|
||||
for suffix in ('', ' 3'):
|
||||
with self.subTest(provider=provider, suffix=suffix):
|
||||
self.assertEqual(self.read(f'1 0 {provider}{suffix}'),
|
||||
(1, provider, 3, 640, 360))
|
||||
|
||||
def test_one_and_two_fields_keep_provider(self):
|
||||
self.assertEqual(self.read('1'), (1, 5, 3, 1920, 1080))
|
||||
self.assertEqual(self.read('1 0'), (1, 5, 3, 640, 360))
|
||||
|
||||
def test_invalid_provider_keeps_previous_provider(self):
|
||||
for provider in (-1, self.providers, 999):
|
||||
for suffix in ('', ' 2'):
|
||||
with self.subTest(provider=provider, suffix=suffix):
|
||||
aspect, size = (2, (640, 400)) if suffix else (3, (640, 360))
|
||||
self.assertEqual(self.read(f'1 0 {provider}{suffix}'), (1, 5, aspect, *size))
|
||||
|
||||
def test_invalid_other_fields_do_not_block_valid_provider(self):
|
||||
for text in ('-1 -1 0 -1', '5 999 0 6'):
|
||||
with self.subTest(text=text):
|
||||
self.assertEqual(self.read(text), (2, 0, 3, 1920, 1080))
|
||||
|
||||
def test_aspect_is_applied_before_output_lookup(self):
|
||||
self.assertEqual(self.read('1 0 0 2'), (1, 0, 2, 640, 400))
|
||||
|
||||
def test_missing_empty_and_non_numeric_requests(self):
|
||||
for text in (None, '', 'bad', 'bad 0 0 3'):
|
||||
with self.subTest(text=text):
|
||||
self.assertEqual(self.read(text), (2, 5, 3, 1920, 1080))
|
||||
|
||||
def test_partial_requests_apply_only_scanned_fields(self):
|
||||
self.assertEqual(self.read('1 0 bad 2'), (1, 5, 3, 640, 360))
|
||||
self.assertEqual(self.read('1 0 0 bad'), (1, 0, 3, 640, 360))
|
||||
|
||||
def test_polling_interval_is_unchanged(self):
|
||||
self.assertEqual(self.read('1 0 0 3', frames=63), (2, 5, 3, 1920, 1080))
|
||||
self.assertEqual(self.read('1 0 0 3', frames=64), (1, 0, 3, 640, 360))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
@@ -0,0 +1,40 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 bbport contributors
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "launcher"))
|
||||
import bbport_shortcut # noqa: E402
|
||||
|
||||
|
||||
class ShortcutTest(unittest.TestCase):
|
||||
def test_exec_quotes_spaces_and_specials(self):
|
||||
self.assertEqual(bbport_shortcut.exec_quote("/a b/Bloodborne.AppImage"),
|
||||
'"/a b/Bloodborne.AppImage"')
|
||||
self.assertEqual(bbport_shortcut.exec_quote('/x/"$`\\'), '"/x/\\"\\$\\`\\\\"')
|
||||
|
||||
def test_entry_fields(self):
|
||||
text = bbport_shortcut.entry_text("/games/Bloodborne.AppImage", "/data/bloodborne.png")
|
||||
lines = text.splitlines()
|
||||
self.assertEqual(lines[0], "[Desktop Entry]")
|
||||
self.assertIn('Exec="/games/Bloodborne.AppImage"', lines)
|
||||
self.assertIn("Icon=/data/bloodborne.png", lines)
|
||||
self.assertIn("StartupWMClass=io.github.bbport.Launcher", lines)
|
||||
|
||||
def test_applications_dir_follows_xdg_data_home(self):
|
||||
self.assertEqual(bbport_shortcut.applications_dir({"XDG_DATA_HOME": "/d"}),
|
||||
Path("/d/applications"))
|
||||
|
||||
def test_write_entry_modes(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
menu = bbport_shortcut.write_entry(Path(tmp) / "apps", "/a", "/i")
|
||||
self.assertEqual(menu.stat().st_mode & 0o777, 0o644)
|
||||
desk = bbport_shortcut.write_entry(Path(tmp) / "desk", "/a", "/i", trusted=True)
|
||||
self.assertEqual(desk.stat().st_mode & 0o777, 0o755)
|
||||
self.assertEqual(desk.read_text(), bbport_shortcut.entry_text("/a", "/i"))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in new issue
Block a user