From b64dcd2f561d8251223a3154e6a5e9aed441061c Mon Sep 17 00:00:00 2001 From: Lander Gallastegi Date: Tue, 12 Nov 2024 08:26:48 +0100 Subject: [PATCH 01/11] Assert fix (#1521) --- .../ir/passes/resource_tracking_pass.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp index 586785e6a..7d29c845d 100644 --- a/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp +++ b/src/shader_recompiler/ir/passes/resource_tracking_pass.cpp @@ -690,9 +690,9 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip IR::Inst* body = inst.Arg(1).InstRecursive(); const auto [coords, arg] = [&] -> std::pair { switch (image.GetType()) { - case AmdGpu::ImageType::Color1D: // x + case AmdGpu::ImageType::Color1D: // x, [lod] return {body->Arg(0), body->Arg(1)}; - case AmdGpu::ImageType::Color1DArray: // x, slice + case AmdGpu::ImageType::Color1DArray: // x, slice, [lod] [[fallthrough]]; case AmdGpu::ImageType::Color2D: // x, y, [lod] [[fallthrough]]; @@ -703,9 +703,9 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip case AmdGpu::ImageType::Color2DMsaaArray: // x, y, slice. (sample is passed on different // argument) [[fallthrough]]; - case AmdGpu::ImageType::Color3D: // x, y, z + case AmdGpu::ImageType::Color3D: // x, y, z, [lod] return {ir.CompositeConstruct(body->Arg(0), body->Arg(1), body->Arg(2)), body->Arg(3)}; - case AmdGpu::ImageType::Cube: // x, y, face + case AmdGpu::ImageType::Cube: // x, y, face, [lod] return {PatchCubeCoord(ir, body->Arg(0), body->Arg(1), body->Arg(2), is_storage, inst_info.is_array), body->Arg(3)}; @@ -717,8 +717,8 @@ void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descrip if (inst_info.has_lod) { ASSERT(inst.GetOpcode() == IR::Opcode::ImageFetch); - ASSERT(image.GetType() == AmdGpu::ImageType::Color2D || - image.GetType() == AmdGpu::ImageType::Color2DArray); + ASSERT(image.GetType() != AmdGpu::ImageType::Color2DMsaa && + image.GetType() != AmdGpu::ImageType::Color2DMsaaArray); inst.SetArg(3, arg); } else if (image.GetType() == AmdGpu::ImageType::Color2DMsaa || image.GetType() == AmdGpu::ImageType::Color2DMsaaArray) { From f5618e03429759e086cd9c6a8a1cf3488a3e1faf Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Mon, 11 Nov 2024 23:27:30 -0800 Subject: [PATCH 02/11] imgui: Dispatch SDL text input requests to main thread on macOS. (#1519) --- src/imgui/renderer/imgui_impl_sdl3.cpp | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/src/imgui/renderer/imgui_impl_sdl3.cpp b/src/imgui/renderer/imgui_impl_sdl3.cpp index 230d396f0..60b440c24 100644 --- a/src/imgui/renderer/imgui_impl_sdl3.cpp +++ b/src/imgui/renderer/imgui_impl_sdl3.cpp @@ -11,6 +11,7 @@ #include #if defined(__APPLE__) #include +#include #endif #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN @@ -71,7 +72,14 @@ static void PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlat auto window_id = (SDL_WindowID)(intptr_t)viewport->PlatformHandle; SDL_Window* window = SDL_GetWindowFromID(window_id); if ((!data->WantVisible || bd->ime_window != window) && bd->ime_window != nullptr) { - SDL_StopTextInput(bd->ime_window); + auto stop_input = [&bd] { SDL_StopTextInput(bd->ime_window); }; +#ifdef __APPLE__ + dispatch_sync(dispatch_get_main_queue(), ^{ + stop_input(); + }); +#else + stop_input(); +#endif bd->ime_window = nullptr; } if (data->WantVisible) { @@ -80,8 +88,17 @@ static void PlatformSetImeData(ImGuiContext*, ImGuiViewport* viewport, ImGuiPlat r.y = (int)data->InputPos.y; r.w = 1; r.h = (int)data->InputLineHeight; - SDL_SetTextInputArea(window, &r, 0); - SDL_StartTextInput(window); + const auto start_input = [&window, &r] { + SDL_SetTextInputArea(window, &r, 0); + SDL_StartTextInput(window); + }; +#ifdef __APPLE__ + dispatch_sync(dispatch_get_main_queue(), ^{ + start_input(); + }); +#else + start_input(); +#endif bd->ime_window = window; } } From 8a15d68a8d7f79390213ddab454fc6a32ab8d824 Mon Sep 17 00:00:00 2001 From: kalaposfos13 <153381648+kalaposfos13@users.noreply.github.com> Date: Tue, 12 Nov 2024 08:31:56 +0100 Subject: [PATCH 03/11] Update Hungarian translation (#1518) --- src/qt_gui/translations/hu_HU.ts | 120 +++++++++++++++---------------- 1 file changed, 60 insertions(+), 60 deletions(-) diff --git a/src/qt_gui/translations/hu_HU.ts b/src/qt_gui/translations/hu_HU.ts index 86279b2de..a43b8d371 100644 --- a/src/qt_gui/translations/hu_HU.ts +++ b/src/qt_gui/translations/hu_HU.ts @@ -62,7 +62,7 @@ Select which directory you want to install to. - Select which directory you want to install to. + Válassza ki a mappát a játékok telepítésére. @@ -90,7 +90,7 @@ The value for location to install games is not valid. - A játékok telepítéséhez megadott érték nem érvényes. + A játékok telepítéséhez megadott útvonal nem érvényes. @@ -108,7 +108,7 @@ SFO Viewer - SFO Néző + SFO Nézegető @@ -158,22 +158,22 @@ Delete... - Delete... + Törlés... Delete Game - Delete Game + Játék törlése Delete Update - Delete Update + Frissítések törlése Delete DLC - Delete DLC + DLC-k törlése @@ -203,27 +203,27 @@ Game - Game + Játék requiresEnableSeparateUpdateFolder_MSG - This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. + Ehhez a funkcióhoz szükséges a 'Külön Frissítési Mappa Engedélyezése' opció, hogy működjön. Ha használni akarja, először engedélyezze azt. This game has no update to delete! - This game has no update to delete! + Ehhez a játékhoz nem tartozik törlendő frissítés! Update - Update + Frissítés This game has no DLC to delete! - This game has no DLC to delete! + Ehhez a játékhoz nem tartozik törlendő DLC! @@ -238,7 +238,7 @@ Are you sure you want to delete %1's %2 directory? - Are you sure you want to delete %1's %2 directory? + Biztosan törölni akarja a %1's %2 mappát? @@ -246,7 +246,7 @@ Open/Add Elf Folder - Efl Mappa Megnyitása/Hozzáadása + ELF Mappa Megnyitása/Hozzáadása @@ -256,7 +256,7 @@ Boot Game - Játék Bootolása + Játék Indítása @@ -291,12 +291,12 @@ Exit shadPS4 - Kilépés a shadPS4 + Kilépés a shadPS4-ből Exit the application. - Lépjen ki az programból. + Lépjen ki a programból. @@ -341,7 +341,7 @@ Elf Viewer - Elf Néző + Elf Nézegető @@ -356,12 +356,12 @@ Dump Game List - Játék Lista Dumpolása + Játéklista Dumpolása PKG Viewer - PKG Néző + PKG Nézegető @@ -376,17 +376,17 @@ View - Megnézés + Nézet Game List Icons - Játék Könyvtár Ikonok + Játékkönyvtár Ikonok Game List Mode - Játék Könyvtár Mód + Játékkönyvtár Nézet @@ -490,12 +490,12 @@ Enable Fullscreen - Teljesképernyő Engedélyezése + Teljes Képernyő Engedélyezése Enable Separate Update Folder - Enable Separate Update Folder + Külön Frissítési Mappa Engedélyezése @@ -505,12 +505,12 @@ Is PS4 Pro - PS4 Pro + PS4 Pro mód Enable Discord Rich Presence - Engedélyezze a Discord Rich Presence-t + A Discord Rich Presence engedélyezése @@ -560,7 +560,7 @@ Back Button Behavior - Vissza gomb viselkedése + Vissza gomb Viselkedése @@ -693,17 +693,17 @@ * Unsupported Vulkan Version - * Támogatott Vulkan verzió hiányzik + * Nem támogatott Vulkan verzió Download Cheats For All Installed Games - Letöltés csalások minden telepített játékhoz + Csalások letöltése minden telepített játékhoz Download Patches For All Games - Frissítések letöltése minden játékhoz + Javítások letöltése minden játékhoz @@ -713,17 +713,17 @@ You have downloaded cheats for all the games you have installed. - Csalásokat töltöttél le az összes telepített játékhoz. + Minden elérhető csalás letöltődött az összes telepített játékhoz. Patches Downloaded Successfully! - Frissítések sikeresen letöltve! + Javítások sikeresen letöltve! All Patches available for all games have been downloaded. - Az összes játékhoz elérhető frissítés letöltésre került. + Az összes játékhoz elérhető javítás letöltésre került. @@ -773,7 +773,7 @@ PKG Version %1 is older than installed version: - A %1-es PKG verzió régebbi, mint a telepített verzió: + A(z) %1-es PKG verzió régebbi, mint a telepített verzió: @@ -793,7 +793,7 @@ Would you like to install DLC: %1? - Szeretné telepíteni a DLC-t: %1? + Szeretné telepíteni a %1 DLC-t? @@ -846,7 +846,7 @@ defaultTextEdit_MSG - A csalások/patchek kísérleti jellegűek.\nHasználja őket óvatosan.\n\nTöltse le a csalásokat egyesével a repository kiválasztásával és a letöltés gombra kattintással.\nA Patches fül alatt egyszerre letöltheti az összes patchet, választhat, melyeket szeretné használni, és elmentheti a választását.\n\nMivel nem fejlesztjük a csalásokat/patch-eket,\nkérjük, jelentse a problémákat a csalás szerzőjének.\n\nKészített egy új csalást? Látogasson el ide:\nhttps://github.com/shadps4-emu/ps4_cheats + A csalások/javítások kísérleti jellegűek.\nHasználja őket óvatosan.\n\nTöltse le a csalásokat egyesével a tároló kiválasztásával és a letöltés gombra kattintással.\nA Javítások fül alatt egyszerre letöltheti az összes javítást, majd választhat, melyeket szeretné használni, és elmentheti a választását.\n\nMivel nem mi fejlesztjük a csalásokat/patch-eket,\nkérjük, jelentse a problémákat a csalás szerzőjének.\n\nKészített egy új csalást? Látogasson el ide:\nhttps://github.com/shadps4-emu/ps4_cheats @@ -1011,7 +1011,7 @@ CheatsNotFound_MSG - Nincs található csalás ezen a játékverzión ebben a kiválasztott tárolóban,próbálj meg egy másik tárolót vagy a játék egy másik verzióját. + Nincs található csalás ezen a játékverzión ebben a kiválasztott tárolóban, próbálj meg egy másik tárolót vagy a játék egy másik verzióját. @@ -1041,7 +1041,7 @@ DownloadComplete_MSG - Frissítések sikeresen letöltve! Minden elérhető frissítés letöltésre került, nem szükséges egyesével letölteni őket minden játékhoz, mint a csalások esetében. Ha a javítás nem jelenik meg, lehet, hogy nem létezik a játék adott sorozatszámához és verziójához. + Frissítések sikeresen letöltve! Minden elérhető frissítés letöltésre került, nem szükséges egyesével letölteni őket minden játékhoz, mint a csalások esetében. Ha a javítások nem jelennek meg, lehet, hogy nem léteznek a játék adott sorozatszámához és verziójához. @@ -1061,7 +1061,7 @@ The downloaded patch only works on version: %1 - A letöltött javítás csak a(z) %1 verzión működik + A letöltött javításhoz a(z) %1 verzió működik @@ -1096,7 +1096,7 @@ Directory does not exist: - A könyvtár nem létezik: + A mappa nem létezik: @@ -1159,22 +1159,22 @@ separateUpdatesCheckBox - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + Külön Frissítéi Mappa Engedélyezése:\nEngedélyezi a frissítések külön mappába helyezését, a könnyű kezelésük érdekében. showSplashCheckBox - Indító képernyő megjelenítése:\nMegjeleníti a játék indító képernyőjét (különleges képet) a játék elindításakor. + Indítóképernyő megjelenítése:\nMegjeleníti a játék indítóképernyőjét (különleges képet) a játék elindításakor. ps4proCheckBox - PS4 Pro:\nAz emulátort PS4 PRO-ként kezeli, ami engedélyezheti a speciális funkciókat olyan játékokban, amelyek támogatják. + PS4 Pro:\nAz emulátort PS4 PRO-ként kezeli, ami engedélyezhet speciális funkciókat olyan játékokban, amelyek támogatják azt. discordRPCCheckbox - Engedélyezze a Discord Rich Presence-t:\nMegjeleníti az emulator ikonját és a kapcsolódó információkat a Discord profilján. + A Discord Rich Presence engedélyezése:\nMegjeleníti az emulator ikonját és a kapcsolódó információkat a Discord profilján. @@ -1199,17 +1199,17 @@ GUIgroupBox - Játék címzene lejátszása:\nHa a játék támogatja, engedélyezze a speciális zene lejátszását, amikor a játékot kiválasztja a GUI-ban. + Játék címzene lejátszása:\nHa a játék támogatja, engedélyezze egy speciális zene lejátszását, amikor a játékot kiválasztja a GUI-ban. hideCursorGroupBox - Akurátor elrejtése:\nVálassza ki, mikor tűnjön el az egérkurzor:\nSoha: Az egér mindig látható.\nInaktív: Állítson be egy időt, amikor inaktív állapotban eltűnik.\nMindig: soha nem látja az egeret. + Kurzor elrejtése:\nVálassza ki, mikor tűnjön el az egérmutató:\nSoha: Az egér mindig látható.\nInaktív: Állítson be egy időt, amennyi idő mozdulatlanság után eltűnik.\nMindig: az egér mindig el lesz rejtve. idleTimeoutGroupBox - Állítson be egy időt, ameddig az egér inaktív állapot után eltűnik. + Állítson be egy időt, ami után egér inaktív állapotban eltűnik. @@ -1234,17 +1234,17 @@ Touchpad Left - Érintőpad Balra + Érintőpad Bal Touchpad Right - Érintőpad Jobbra + Érintőpad Jobb Touchpad Center - Érintőpad Középen + Érintőpad Közép @@ -1254,7 +1254,7 @@ graphicsAdapterGroupBox - Grafikus eszköz:\nTöbb GPU-s rendszereken válassza ki a GPU-t, amelyet az emulátor használ a legördülő listából,\nvagy válassza az "Auto Select" lehetőséget, hogy automatikusan meghatározza azt. + Grafikus eszköz:\nTöbb GPU-s rendszereken válassza ki, melyik GPU-t használja az emulátor a legördülő listából,\nvagy válassza az "Auto Select" lehetőséget, hogy automatikusan kiválassza azt. @@ -1264,7 +1264,7 @@ heightDivider - Vblank osztó:\nAz emulátor frissítési sebessége e számot megszorozva működik. Ennek megváltoztatása kedvezőtlen hatásokat okozhat, például növelheti a játék sebességét, vagy megszakíthat kritikus játékfunkciókat, amelyek nem számítanak arra, hogy ez megváltozik! + Vblank elosztó:\nAz emulátor frissítési sebessége e számot megszorozva működik. Ennek megváltoztatása kedvezőtlen hatásokat okozhat, például növelheti a játék sebességét, vagy megszakíthat kritikus játékfunkciókat, amelyek nem számítanak arra, hogy ez megváltozik! @@ -1279,7 +1279,7 @@ gameFoldersBox - Játék mappák:\nA mappák listája az telepített játékok ellenőrzésére. + Játék mappák:\nA mappák listája, ahol telepített játékok vannak. @@ -1420,7 +1420,7 @@ Latest Version - Legújabb verzió + Új verzió @@ -1430,7 +1430,7 @@ Show Changelog - Módosítások megjelenítése + Változások megjelenítése @@ -1445,17 +1445,17 @@ No - Nem + Mégse Hide Changelog - Módosítások elrejtése + Változások elrejtése Changes - Módosítások + Változások @@ -1488,4 +1488,4 @@ A frissítési szkript fájl létrehozása nem sikerült - \ No newline at end of file + From 85f45d2788bacd430343fbc27577b9da2d79b442 Mon Sep 17 00:00:00 2001 From: Florian Piesche Date: Tue, 12 Nov 2024 07:32:56 +0000 Subject: [PATCH 04/11] Add scalable vector redraw of shadps4 icon (#1501) * Add scalable vector redraw of shadps4 icon * Update icon name in desktop file * Fix svg --- .github/linux-appimage-qt.sh | 2 +- .github/linux-appimage-sdl.sh | 2 +- .github/shadps4.desktop | 2 +- CMakeLists.txt | 1 + REUSE.toml | 1 + src/images/net.shadps4.shadPS4.svg | 2 ++ 6 files changed, 7 insertions(+), 3 deletions(-) create mode 100644 src/images/net.shadps4.shadPS4.svg diff --git a/.github/linux-appimage-qt.sh b/.github/linux-appimage-qt.sh index 8a5f340f6..d176b17dc 100755 --- a/.github/linux-appimage-qt.sh +++ b/.github/linux-appimage-qt.sh @@ -27,7 +27,7 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin -./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --plugin qt +./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so ./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage mv shadPS4-x86_64.AppImage Shadps4-qt.AppImage diff --git a/.github/linux-appimage-sdl.sh b/.github/linux-appimage-sdl.sh index cf0ce4de1..d747abbe6 100755 --- a/.github/linux-appimage-sdl.sh +++ b/.github/linux-appimage-sdl.sh @@ -17,5 +17,5 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh # Build AppImage ./linuxdeploy-x86_64.AppImage --appdir AppDir ./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir -./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/.github/shadps4.png --output appimage +./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --output appimage mv shadPS4-x86_64.AppImage Shadps4-sdl.AppImage diff --git a/.github/shadps4.desktop b/.github/shadps4.desktop index 6dc663718..b9070c4f4 100644 --- a/.github/shadps4.desktop +++ b/.github/shadps4.desktop @@ -3,7 +3,7 @@ Name=shadPS4 Exec=shadps4 Terminal=false Type=Application -Icon=shadps4 +Icon=net.shadps4.shadPS4 Comment=shadPS4 Emulator Categories=Game; StartupWMClass=shadps4; diff --git a/CMakeLists.txt b/CMakeLists.txt index 439663352..e0e877a52 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -945,4 +945,5 @@ install(TARGETS shadps4 BUNDLE DESTINATION .) if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux") install(FILES ".github/shadps4.desktop" DESTINATION "share/applications") install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps") + install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps") endif() diff --git a/REUSE.toml b/REUSE.toml index e1a266030..b04969735 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -35,6 +35,7 @@ path = [ "src/images/stop_icon.png", "src/images/shadPS4.icns", "src/images/shadps4.ico", + "src/images/net.shadps4.shadPS4.svg", "src/images/themes_icon.png", "src/images/update_icon.png", "src/shadps4.qrc", diff --git a/src/images/net.shadps4.shadPS4.svg b/src/images/net.shadps4.shadPS4.svg new file mode 100644 index 000000000..2d954b12c --- /dev/null +++ b/src/images/net.shadps4.shadPS4.svg @@ -0,0 +1,2 @@ + + From 0c52d02043404b6fdb00ae01d5eca57ce61c0949 Mon Sep 17 00:00:00 2001 From: squidbus <175574877+squidbus@users.noreply.github.com> Date: Wed, 13 Nov 2024 09:04:13 -0800 Subject: [PATCH 05/11] videodec: Lower sceVideodecDecode log to trace. (#1527) --- src/core/libraries/videodec/videodec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/libraries/videodec/videodec.cpp b/src/core/libraries/videodec/videodec.cpp index 96ece3c5c..8d6ea4988 100644 --- a/src/core/libraries/videodec/videodec.cpp +++ b/src/core/libraries/videodec/videodec.cpp @@ -36,7 +36,7 @@ int PS4_SYSV_ABI sceVideodecDecode(OrbisVideodecCtrl* pCtrlIn, const OrbisVideodecInputData* pInputDataIn, OrbisVideodecFrameBuffer* pFrameBufferInOut, OrbisVideodecPictureInfo* pPictureInfoOut) { - LOG_INFO(Lib_Videodec, "called"); + LOG_TRACE(Lib_Videodec, "called"); if (!pCtrlIn || !pInputDataIn || !pPictureInfoOut) { return ORBIS_VIDEODEC_ERROR_ARGUMENT_POINTER; } From 6ae92c0aac3eec89a26baaad48cb05d9efb9bd27 Mon Sep 17 00:00:00 2001 From: Florian Piesche Date: Thu, 14 Nov 2024 08:56:14 +0000 Subject: [PATCH 06/11] Add FreeDesktop metadata (#1495) --- .github/linux-appimage-qt.sh | 2 +- .github/linux-appimage-sdl.sh | 2 +- CMakeLists.txt | 6 +- REUSE.toml | 5 +- .../net.shadps4.shadPS4.desktop | 2 +- dist/net.shadps4.shadPS4.metainfo.xml | 63 ++++++++++++++++++ dist/net.shadps4.shadPS4.releases.xml | 23 +++++++ dist/net.shadps4.shadPS4_metadata.pot | 65 +++++++++++++++++++ 8 files changed, 162 insertions(+), 6 deletions(-) rename .github/shadps4.desktop => dist/net.shadps4.shadPS4.desktop (81%) create mode 100644 dist/net.shadps4.shadPS4.metainfo.xml create mode 100644 dist/net.shadps4.shadPS4.releases.xml create mode 100644 dist/net.shadps4.shadPS4_metadata.pot diff --git a/.github/linux-appimage-qt.sh b/.github/linux-appimage-qt.sh index d176b17dc..776eed61e 100755 --- a/.github/linux-appimage-qt.sh +++ b/.github/linux-appimage-qt.sh @@ -27,7 +27,7 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh cp -a "$GITHUB_WORKSPACE/build/translations" AppDir/usr/bin -./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt +./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --plugin qt rm AppDir/usr/plugins/multimedia/libgstreamermediaplugin.so ./linuxdeploy-x86_64.AppImage --appdir AppDir --output appimage mv shadPS4-x86_64.AppImage Shadps4-qt.AppImage diff --git a/.github/linux-appimage-sdl.sh b/.github/linux-appimage-sdl.sh index d747abbe6..7961f5312 100755 --- a/.github/linux-appimage-sdl.sh +++ b/.github/linux-appimage-sdl.sh @@ -17,5 +17,5 @@ chmod a+x linuxdeploy-plugin-checkrt-x86_64.sh # Build AppImage ./linuxdeploy-x86_64.AppImage --appdir AppDir ./linuxdeploy-plugin-checkrt-x86_64.sh --appdir AppDir -./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/.github/shadps4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --output appimage +./linuxdeploy-x86_64.AppImage --appdir AppDir -d "$GITHUB_WORKSPACE"/dist/net.shadps4.shadPS4.desktop -e "$GITHUB_WORKSPACE"/build/shadps4 -i "$GITHUB_WORKSPACE"/src/images/net.shadps4.shadPS4.svg --output appimage mv shadPS4-x86_64.AppImage Shadps4-sdl.AppImage diff --git a/CMakeLists.txt b/CMakeLists.txt index e0e877a52..d320d49e3 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -943,7 +943,9 @@ endif() install(TARGETS shadps4 BUNDLE DESTINATION .) if (ENABLE_QT_GUI AND CMAKE_SYSTEM_NAME STREQUAL "Linux") - install(FILES ".github/shadps4.desktop" DESTINATION "share/applications") - install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps") + install(FILES "dist/net.shadps4.shadPS4.desktop" DESTINATION "share/applications") + install(FILES "dist/net.shadps4.shadPS4.releases.xml" DESTINATION "share/metainfo/releases") + install(FILES "dist/net.shadps4.shadPS4.metainfo.xml" DESTINATION "share/metainfo") + install(FILES ".github/shadps4.png" DESTINATION "share/icons/hicolor/512x512/apps" RENAME "net.shadps4.shadPS4.png") install(FILES "src/images/net.shadps4.shadPS4.svg" DESTINATION "share/icons/hicolor/scalable/apps") endif() diff --git a/REUSE.toml b/REUSE.toml index b04969735..405156231 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -5,9 +5,12 @@ path = [ "REUSE.toml", "CMakeSettings.json", ".github/FUNDING.yml", - ".github/shadps4.desktop", ".github/shadps4.png", ".gitmodules", + "dist/net.shadps4.shadPS4.desktop", + "dist/net.shadps4.shadPS4_metadata.pot", + "dist/net.shadps4.shadPS4.metainfo.xml", + "dist/net.shadps4.shadPS4.releases.xml", "documents/changelog.txt", "documents/Quickstart/2.png", "documents/Screenshots/*", diff --git a/.github/shadps4.desktop b/dist/net.shadps4.shadPS4.desktop similarity index 81% rename from .github/shadps4.desktop rename to dist/net.shadps4.shadPS4.desktop index b9070c4f4..fbefa0566 100644 --- a/.github/shadps4.desktop +++ b/dist/net.shadps4.shadPS4.desktop @@ -4,6 +4,6 @@ Exec=shadps4 Terminal=false Type=Application Icon=net.shadps4.shadPS4 -Comment=shadPS4 Emulator +Comment=PlayStation 4 emulator Categories=Game; StartupWMClass=shadps4; diff --git a/dist/net.shadps4.shadPS4.metainfo.xml b/dist/net.shadps4.shadPS4.metainfo.xml new file mode 100644 index 000000000..bef0bec4c --- /dev/null +++ b/dist/net.shadps4.shadPS4.metainfo.xml @@ -0,0 +1,63 @@ + + + net.shadps4.shadPS4 + shadPS4 + + shadPS4 Contributors + https://github.com/shadps4-emu/shadps4/graphs/contributors + + PS4 Emulator + CC0-1.0 + GPL-2.0 + net.shadps4.shadPS4.desktop + https://shadps4.net/ + +

shadPS4 is an early PlayStation 4 emulator for Windows, Linux and macOS written in C++.

+

The emulator is still early in development, so don't expect a flawless experience. Nonetheless, the emulator can already run a number of commercial games.

+
+ + + https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/1.png + Bloodborne + + + https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/2.png + Hatsune Miku: Project DIVA Future Tone + + + https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/3.png + Yakuza Kiwami + + + https://cdn.jsdelivr.net/gh/shadps4-emu/shadps4@main/documents/Screenshots/4.png + Persona 4 Golden + + + + Game + + + + + + + + + keyboard + + + gamepad + + + offline-only + + + shadps4 + + + emulator + emulation + playstation + ps4 + +
diff --git a/dist/net.shadps4.shadPS4.releases.xml b/dist/net.shadps4.shadPS4.releases.xml new file mode 100644 index 000000000..8da203fe4 --- /dev/null +++ b/dist/net.shadps4.shadPS4.releases.xml @@ -0,0 +1,23 @@ + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.4.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.3.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v.0.2.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/0.1.0 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.3 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.2 + + + https://github.com/shadps4-emu/shadPS4/releases/tag/v0.0.1 + + diff --git a/dist/net.shadps4.shadPS4_metadata.pot b/dist/net.shadps4.shadPS4_metadata.pot new file mode 100644 index 000000000..d77947b7a --- /dev/null +++ b/dist/net.shadps4.shadPS4_metadata.pot @@ -0,0 +1,65 @@ +msgid "" +msgstr "" +"Project-Id-Version: PACKAGE VERSION\n" +"POT-Creation-Date: 2024-11-08 09:07+0000\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#. (itstool) path: component/name +#: ./net.shadps4.shadPS4.metainfo.xml:4 +msgid "shadPS4" +msgstr "" + +#. (itstool) path: developer/name +#: ./net.shadps4.shadPS4.metainfo.xml:6 +msgid "shadPS4 Contributors" +msgstr "" + +#. (itstool) path: component/summary +#: ./net.shadps4.shadPS4.metainfo.xml:9 +msgid "PS4 Emulator" +msgstr "" + +#. (itstool) path: description/p +#: ./net.shadps4.shadPS4.metainfo.xml:16 +msgid "shadPS4 is an early PlayStation 4 emulator for Windows, Linux and macOS written in C++." +msgstr "" + +#. (itstool) path: description/p +#: ./net.shadps4.shadPS4.metainfo.xml:17 +msgid "The emulator is still early in development, so don't expect a flawless experience. Nonetheless, the emulator can already run a number of commercial games." +msgstr "" + +#. (itstool) path: screenshot/caption +#: ./net.shadps4.shadPS4.metainfo.xml:22 +msgid "Bloodborne" +msgstr "" + +#. (itstool) path: screenshot/caption +#: ./net.shadps4.shadPS4.metainfo.xml:26 +msgid "Hatsune Miku: Project DIVA Future Tone" +msgstr "" + +#. (itstool) path: screenshot/caption +#: ./net.shadps4.shadPS4.metainfo.xml:30 +msgid "Yakuza Kiwami" +msgstr "" + +#. (itstool) path: screenshot/caption +#: ./net.shadps4.shadPS4.metainfo.xml:34 +msgid "Persona 4 Golden" +msgstr "" + +#. (itstool) path: keywords/keyword +#: ./net.shadps4.shadPS4.metainfo.xml:59 +msgid "emulator" +msgstr "" + +#. (itstool) path: keywords/keyword +#: ./net.shadps4.shadPS4.metainfo.xml:60 +msgid "emulation" +msgstr "" From 8e281575b582eba835045957fff64346eacfae6e Mon Sep 17 00:00:00 2001 From: Martin <67326368+Martini-141@users.noreply.github.com> Date: Thu, 14 Nov 2024 11:00:59 +0100 Subject: [PATCH 07/11] =?UTF-8?q?Update=20Norwegian=20Bokm=C3=A5l=20transl?= =?UTF-8?q?ations=20(#1525)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * specify nb_NO * Update Norwegian Bokmål translation * change patch wording nb_NO --- src/qt_gui/settings_dialog.cpp | 4 +- src/qt_gui/translations/{nb.ts => nb_NO.ts} | 306 ++++++++++---------- 2 files changed, 155 insertions(+), 155 deletions(-) rename src/qt_gui/translations/{nb.ts => nb_NO.ts} (81%) diff --git a/src/qt_gui/settings_dialog.cpp b/src/qt_gui/settings_dialog.cpp index da2e3bd11..83582663a 100644 --- a/src/qt_gui/settings_dialog.cpp +++ b/src/qt_gui/settings_dialog.cpp @@ -31,7 +31,7 @@ QStringList languageNames = {"Arabic", "Italian", "Japanese", "Korean", - "Norwegian", + "Norwegian (Bokmaal)", "Polish", "Portuguese (Brazil)", "Portuguese (Portugal)", @@ -548,4 +548,4 @@ bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) { } } return QDialog::eventFilter(obj, event); -} \ No newline at end of file +} diff --git a/src/qt_gui/translations/nb.ts b/src/qt_gui/translations/nb_NO.ts similarity index 81% rename from src/qt_gui/translations/nb.ts rename to src/qt_gui/translations/nb_NO.ts index 940c6c9b6..e02f24182 100644 --- a/src/qt_gui/translations/nb.ts +++ b/src/qt_gui/translations/nb_NO.ts @@ -8,7 +8,7 @@ About shadPS4 - About shadPS4 + Om shadPS4 @@ -18,12 +18,12 @@ shadPS4 is an experimental open-source emulator for the PlayStation 4. - shadPS4 is an experimental open-source emulator for the PlayStation 4. + shadPS4 er en eksperimentell åpen kildekode-etterligner for PlayStation 4. This software should not be used to play games you have not legally obtained. - This software should not be used to play games you have not legally obtained. + Denne programvaren skal ikke brukes til å spille spill du ikke har fått lovlig. @@ -31,7 +31,7 @@ Open Folder - Open Folder + Åpne mappe @@ -39,17 +39,17 @@ Loading game list, please wait :3 - Loading game list, please wait :3 + Laster spill-liste, vennligst vent :3 Cancel - Cancel + Avbryt Loading... - Loading... + Laster... @@ -57,12 +57,12 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Velg mappe Select which directory you want to install to. - Select which directory you want to install to. + Velg hvilken mappe du vil installere til. @@ -70,27 +70,27 @@ shadPS4 - Choose directory - shadPS4 - Choose directory + shadPS4 - Velg mappe Directory to install games - Directory to install games + Mappe for å installere spill Browse - Browse + Bla gjennom Error - Error + Feil The value for location to install games is not valid. - The value for location to install games is not valid. + Verdien for mappen for å installere spill er ikke gyldig. @@ -98,22 +98,22 @@ Create Shortcut - Create Shortcut + Lag snarvei Cheats / Patches - Juks / Oppdateringer + Juks / Programrettelse SFO Viewer - SFO Viewer + SFO Viser Trophy Viewer - Trophy Viewer + Trofé Viser @@ -138,92 +138,92 @@ Copy info... - Copy info... + Kopier info... Copy Name - Copy Name + Kopier Navn Copy Serial - Copy Serial + Kopier Serienummer Copy All - Copy All + Kopier Alle Delete... - Delete... + Slett... Delete Game - Delete Game + Slett Spill Delete Update - Delete Update + Slett Oppdatering Delete DLC - Delete DLC + Slett DLC Shortcut creation - Shortcut creation + Snarvei opprettelse Shortcut created successfully!\n %1 - Shortcut created successfully!\n %1 + Snarvei opprettet!\n %1 Error - Error + Feil Error creating shortcut!\n %1 - Error creating shortcut!\n %1 + Feil ved opprettelse av snarvei!\n %1 Install PKG - Install PKG + Installer PKG Game - Game + Spill requiresEnableSeparateUpdateFolder_MSG - This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it. + Denne funksjonen krever 'Aktiver seperat oppdateringsmappe' konfigurasjonsalternativet. Hvis du vil bruke denne funksjonen, vennligst aktiver den. This game has no update to delete! - This game has no update to delete! + Dette spillet har ingen oppdatering å slette! Update - Update + Oppdater This game has no DLC to delete! - This game has no DLC to delete! + Dette spillet har ingen DLC å slette! @@ -233,12 +233,12 @@ Delete %1 - Delete %1 + Slett %1 Are you sure you want to delete %1's %2 directory? - Are you sure you want to delete %1's %2 directory? + Er du sikker på at du vil slette %1's %2 directory? @@ -246,17 +246,17 @@ Open/Add Elf Folder - Open/Add Elf Folder + Åpne/Legg til Elf-mappe Install Packages (PKG) - Install Packages (PKG) + Installer Pakker (PKG) Boot Game - Boot Game + Start Spill @@ -266,57 +266,57 @@ About shadPS4 - About shadPS4 + Om shadPS4 Configure... - Configure... + Konfigurer... Install application from a .pkg file - Install application from a .pkg file + Installer fra en .pkg fil Recent Games - Recent Games + Nylige Spill Exit - Exit + Avslutt Exit shadPS4 - Exit shadPS4 + Avslutt shadPS4 Exit the application. - Exit the application. + Avslutt programmet. Show Game List - Show Game List + Vis Spill-listen Game List Refresh - Game List Refresh + Oppdater Spill-listen Tiny - Tiny + Bitteliten Small - Small + Liten @@ -326,82 +326,82 @@ Large - Large + Stor List View - List View + Liste-visning Grid View - Grid View + Rute-visning Elf Viewer - Elf Viewer + Elf-visning Game Install Directory - Game Install Directory + Spillinstallasjons-mappe Download Cheats/Patches - Last ned Juks / Oppdateringer + Last ned Juks /Programrettelse Dump Game List - Dump Game List + Dump Spill-liste PKG Viewer - PKG Viewer + PKG Viser Search... - Search... + Søk... File - File + Fil View - View + Oversikt Game List Icons - Game List Icons + Spill-liste Ikoner Game List Mode - Game List Mode + Spill-liste Modus Settings - Settings + Innstillinger Utils - Utils + Verktøy Themes - Themes + Tema @@ -411,32 +411,32 @@ Dark - Dark + Mørk Light - Light + Lys Green - Green + Grønn Blue - Blue + Blå Violet - Violet + Lilla toolBar - toolBar + Verktøylinje @@ -444,7 +444,7 @@ Open Folder - Open Folder + Åpne Mappe @@ -452,7 +452,7 @@ Trophy Viewer - Trophy Viewer + Trofé Viser @@ -460,12 +460,12 @@ Settings - Settings + Innstillinger General - General + Generell @@ -475,37 +475,37 @@ Console Language - Console Language + Konsollspråk Emulator Language - Emulator Language + Etterlignerspråk Emulator - Emulator + Etterligner Enable Fullscreen - Enable Fullscreen + Aktiver Fullskjerm Enable Separate Update Folder - Enable Separate Update Folder + Aktiver Seperat Oppdateringsmappe Show Splash - Show Splash + Vis Velkomst Is PS4 Pro - Is PS4 Pro + Er PS4 Pro @@ -515,7 +515,7 @@ Username - Username + Brukernavn @@ -540,17 +540,17 @@ Cursor - Markør + Musepeker Hide Cursor - Skjul markør + Skjul musepeker Hide Cursor Idle Timeout - Timeout for å skjule markør ved inaktivitet + Skjul musepeker ved inaktivitet @@ -560,47 +560,47 @@ Back Button Behavior - Tilbakeknapp atferd + Tilbakeknapp Atferd Graphics - Graphics + Grafikk Graphics Device - Graphics Device + Grafikkenhet Width - Width + Bredde Height - Height + Høyde Vblank Divider - Vblank Divider + Vblank Skillelinje Advanced - Advanced + Avansert Enable Shaders Dumping - Enable Shaders Dumping + Aktiver Skyggelegger Dumping Enable NULL GPU - Enable NULL GPU + Aktiver NULL GPU @@ -625,27 +625,27 @@ Debug - Debug + Feilretting Enable Debug Dumping - Enable Debug Dumping + Aktiver Feilretting Dumping Enable Vulkan Validation Layers - Enable Vulkan Validation Layers + Aktiver Vulkan Valideringslag Enable Vulkan Synchronization Validation - Enable Vulkan Synchronization Validation + Aktiver Vulkan Synkroniseringslag Enable RenderDoc Debugging - Enable RenderDoc Debugging + Aktiver RenderDoc Feilretting @@ -688,17 +688,17 @@ Game List - Spilliste + Spill-liste * Unsupported Vulkan Version - * Ikke støttet Vulkan-versjon + * Ustøttet Vulkan-versjon Download Cheats For All Installed Games - Last ned jukser for alle installerte spill + Last ned juks for alle installerte spill @@ -713,17 +713,17 @@ You have downloaded cheats for all the games you have installed. - Du har lastet ned jukser for alle spillene du har installert. + Du har lastet ned juks for alle spillene du har installert. Patches Downloaded Successfully! - Oppdateringer lastet ned vellykket! + Programrettelser lastet ned vellykket! All Patches available for all games have been downloaded. - Alle oppdateringer tilgjengelige for alle spillene har blitt lastet ned. + Programrettelser tilgjengelige for alle spill har blitt lastet ned. @@ -758,7 +758,7 @@ Patch detected! - Oppdatering oppdaget! + Programrettelse oppdaget! @@ -783,7 +783,7 @@ Would you like to install Patch: - Ønsker du å installere oppdateringen: + Ønsker du å installere programrettelsen: @@ -818,12 +818,12 @@ Extracting PKG %1/%2 - Ekstraherer PKG %1/%2 + Pakker ut PKG %1/%2 Extraction Finished - Ekstrahering fullført + Utpakking fullført @@ -833,7 +833,7 @@ File doesn't appear to be a valid PKG file - Fil ser ikke ut til å være en gyldig PKG-fil + Filen ser ikke ut til å være en gyldig PKG-fil @@ -841,12 +841,12 @@ Cheats / Patches - Jukser / Oppdateringer + Juks / Programrettelse defaultTextEdit_MSG - Cheats/Patches er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned cheats individuelt ved å velge depotet og klikke på nedlastingsknappen.\nPå fanen Patches kan du laste ned alle patches samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Cheats/Patches,\nvær vennlig å rapportere problemer til cheat-utvikleren.\n\nHar du laget en ny cheat? Besøk:\nhttps://github.com/shadps4-emu/ps4_cheats + Juks/programrettelse er eksperimentelle.\nBruk med forsiktighet.\n\nLast ned juks individuelt ved å velge pakkebrønn og klikke på nedlastingsknappen.\nPå fanen programrettelse kan du laste ned alle programrettelser samtidig, velge hvilke du ønsker å bruke, og lagre valget ditt.\n\nSiden vi ikke utvikler Juksene/Programrettelsene,\nvær vennlig å rapportere problemer til juks-utvikleren.\n\nHar du laget en ny juks? Besøk:\nhttps://github.com/shadps4-emu/ps4_cheats @@ -876,12 +876,12 @@ Repository: - Depot: + Pakkebrønn: Download Cheats - Last ned jukser + Last ned juks @@ -906,12 +906,12 @@ Select Patch File: - Velg oppdateringsfil: + Velg programrettelse-filen: Download Patches - Last ned oppdateringer + Last ned programrettelse @@ -926,7 +926,7 @@ Patches - Oppdateringer + Programrettelse @@ -936,7 +936,7 @@ No patch selected. - Ingen oppdatering valgt. + Ingen programrettelse valgt. @@ -946,7 +946,7 @@ No patch file found for the current serial. - Ingen oppdateringsfil funnet for det aktuelle serienummeret. + Ingen programrettelse-fil funnet for det aktuelle serienummeret. @@ -961,7 +961,7 @@ Failed to parse XML: - Feil ved parsing av XML: + Feil ved tolkning av XML: @@ -986,12 +986,12 @@ File Exists - Fil eksisterer + Filen eksisterer File already exists. Do you want to replace it? - Fil eksisterer allerede. Ønsker du å erstatte den? + Filen eksisterer allerede. Ønsker du å erstatte den? @@ -1011,7 +1011,7 @@ CheatsNotFound_MSG - Ingen jukser funnet for dette spillet i denne versjonen av det valgte depotet,prøv et annet depot eller en annen versjon av spillet. + Ingen juks funnet for dette spillet i denne versjonen av den valgte pakkebrønnen,prøv en annen pakkebrønn eller en annen versjon av spillet. @@ -1021,7 +1021,7 @@ CheatsDownloadedSuccessfully_MSG - Du har lastet ned jukser vellykket for denne versjonen av spillet fra det valgte depotet. Du kan prøve å laste ned fra et annet depot, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. + Du har lastet ned jukser vellykket for denne versjonen av spillet fra den valgte pakkebrønnen. Du kan prøve å laste ned fra en annen pakkebrønn, hvis det er tilgjengelig, vil det også være mulig å bruke det ved å velge filen fra listen. @@ -1041,7 +1041,7 @@ DownloadComplete_MSG - Oppdateringer lastet ned vellykket! Alle oppdateringer tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med jukser. Hvis oppdateringen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. + Oppdateringer lastet ned vellykket! Alle programrettelsene tilgjengelige for alle spill har blitt lastet ned, det er ikke nødvendig å laste dem ned individuelt for hvert spill som skjer med jukser. Hvis programrettelsen ikke vises, kan det hende at den ikke finnes for den spesifikke serienummeret og versjonen av spillet. @@ -1061,7 +1061,7 @@ The downloaded patch only works on version: %1 - Den nedlastede patchen fungerer bare på versjon: %1 + Den nedlastede programrettelsen fungerer bare på versjon: %1 @@ -1071,7 +1071,7 @@ Incompatibility Notice - Inkompatibilitetsvarsel + Inkompatibilitets-varsel @@ -1096,7 +1096,7 @@ Directory does not exist: - Direktory eksisterer ikke: + Mappen eksisterer ikke: @@ -1119,7 +1119,7 @@ Save - Lag + Lagre @@ -1139,7 +1139,7 @@ Point your mouse at an option to display its description. - Hold musen over et valg for at vise beskrivelsen. + Pek musen over et alternativ for å vise beskrivelsen. @@ -1149,7 +1149,7 @@ emulatorLanguageGroupBox - Emulatorspråk:\nAngir språket for emulatorens brukergrensesnitt. + Etterlignerspråket:\nAngir språket for etterlignerens brukergrensesnitt. @@ -1159,7 +1159,7 @@ separateUpdatesCheckBox - Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management. + Aktiver separat oppdateringsmappe:\nAktiverer installering av spill i en egen mappe for enkel administrasjon. @@ -1169,12 +1169,12 @@ ps4proCheckBox - Er PS4 Pro:\nFår emulatoren til å fungere som en PS4 PRO, noe som kan aktivere spesielle funksjoner i spill som støtter det. + Er PS4 Pro:\nFår emulatoren til å fungere som en PS4 PRO, noe som kan aktivere spesielle funksjoner i spill som støtter dette. discordRPCCheckbox - Aktiver Discord Rich Presence:\nViser emulatorikonet og relevant informasjon på Discord-profilen din. + Aktiver Discord Rich Presence:\nViser etterlignerikonet og relevant informasjon på Discord-profilen din. @@ -1184,7 +1184,7 @@ logTypeGroupBox - Logtype:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter på emulering. + Logtype:\nAngir om loggvinduets utdata skal synkroniseres for ytelse. Kan ha negative effekter for etterligneren. @@ -1199,17 +1199,17 @@ GUIgroupBox - Spille tittelmusikk:\nHvis et spill støtter det, aktiverer det å spille spesiell musikk når du velger spillet i GUI. + Spille tittelmusikk:\nHvis et spill støtter det, aktiverer spesiell musikk når du velger spillet i menyen. hideCursorGroupBox - Skjul musepeker:\nVelg når musepekeren skal forsvinne:\nAldri: Du vil alltid se musen.\nInaktiv: Sett en tid for at den skal forsvinne etter å ha vært inaktiv.\nAlltid: du vil aldri se musen. + Skjul musepeker:\nVelg når musepekeren skal forsvinne:\nAldri: Du vil alltid se musepekeren.\nInaktiv: Sett en tid for at den skal forsvinne etter å ha vært inaktiv.\nAlltid: du vil aldri se musepekeren. idleTimeoutGroupBox - Sett en tid for når musen forsvinner etter å ha vært inaktiv. + Sett en tid for når musepekeren forsvinner etter å ha vært inaktiv. @@ -1254,27 +1254,27 @@ graphicsAdapterGroupBox - Grafikkdevice:\nI systemer med flere GPU-er, velg GPU-en emulatoren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å bestemme det automatisk. + Grafikkenhet:\nI systemer med flere GPU-er, velg GPU-en etterligneren skal bruke fra rullegardinlisten,\neller velg "Auto Select" for å bestemme det automatisk. resolutionLayout - Bredde/Høyde:\nAngir størrelsen på emulatorkvinduet ved oppstart, som kan endres under spillingen.\nDette er forskjellig fra oppløsningen i spillet. + Bredde/Høyde:\nAngir størrelsen på etterlignerkvinduet ved oppstart, som kan endres under spillingen.\nDette er forskjellig fra oppløsningen i spillet. heightDivider - Vblank divider:\nBilderaten som emulatoren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten på spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! + Vblank Skillelinje:\nBildehastigheten som etterligneren oppdaterer ved, multipliseres med dette tallet. Endring av dette kan ha negative effekter, som å øke hastigheten på spillet, eller ødelegge kritisk spillfunksjonalitet som ikke forventer at dette endres! dumpShadersCheckBox - Aktiver shaderdumping:\nFor teknisk feilsøking lagrer shaderne fra spillet i en mappe mens de gjengis. + Aktiver skyggelegger-dumping:\nFor teknisk feilsøking lagrer skyggeleggene fra spillet i en mappe mens de gjengis. nullGpuCheckBox - Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillrendering som om det ikke var noe grafikkort. + Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillgjengivelse som om det ikke var noe grafikkort. @@ -1294,22 +1294,22 @@ debugDump - Aktiver feilsøking dumping:\nLagrer import- og eksport-symbolene og filoverskriftsinformasjonen til det nåværende kjørende PS4-programmet i en katalog. + Aktiver dumping av feilsøking:\nLagrer import- og eksport-symbolene og filoverskriftsinformasjonen til det nåværende kjørende PS4-programmet i en katalog. vkValidationCheckBox - Aktiver Vulkan valideringslag:\nAktiverer et system som validerer tilstanden til Vulkan-rendereren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre emuleringens oppførsel. + Aktiver Vulkan valideringslag:\nAktiverer et system som validerer tilstanden til Vulkan-gjengiveren og logger informasjon om dens indre tilstand. Dette vil redusere ytelsen og sannsynligvis endre etterlignerens oppførsel. vkSyncValidationCheckBox - Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer timingen av Vulkan-renderingsoppgaver. Dette vil redusere ytelsen og sannsynligvis endre emuleringens oppførsel. + Aktiver Vulkan synkronisering validering:\nAktiverer et system som validerer frekvens tiden av Vulkan-gjengivelsensoppgaver. Dette vil redusere ytelsen og sannsynligvis endre etterlignerens oppførsel. rdocCheckBox - Aktiver RenderDoc feilsøking:\nHvis aktivert, vil emulatoren gi kompatibilitet med Renderdoc for å tillate opptak og analyse av det nåværende renderte bildet. + Aktiver RenderDoc feilsøking:\nHvis aktivert, vil etterligneren gi kompatibilitet med Renderdoc for å tillate opptak og analyse av det nåværende gjengitte bildet. @@ -1337,7 +1337,7 @@ Firmware - Firmware + Fastvare @@ -1488,4 +1488,4 @@ Kunne ikke opprette oppdateringsskriptfilen - \ No newline at end of file + From bf239ebc04c2c2b7240608101193deda130acc5b Mon Sep 17 00:00:00 2001 From: Vladislav Mikhalin Date: Thu, 14 Nov 2024 13:01:20 +0300 Subject: [PATCH 08/11] ajm: handle single-frame decode jobs (+mp3 imrovements) (#1520) * ajm: handle single-frame decode jobs (+mp3 imrovements) * disable breaking the loop in multi-frame if storage is insufficient * simplified gapless decoding --- src/core/libraries/ajm/ajm_at9.cpp | 66 ++--- src/core/libraries/ajm/ajm_at9.h | 10 +- src/core/libraries/ajm/ajm_batch.cpp | 19 +- src/core/libraries/ajm/ajm_instance.cpp | 71 +++-- src/core/libraries/ajm/ajm_instance.h | 34 ++- src/core/libraries/ajm/ajm_mp3.cpp | 367 +++++++++++++++++++----- src/core/libraries/ajm/ajm_mp3.h | 39 ++- 7 files changed, 450 insertions(+), 156 deletions(-) diff --git a/src/core/libraries/ajm/ajm_at9.cpp b/src/core/libraries/ajm/ajm_at9.cpp index 7fff0ff0c..936929ae8 100644 --- a/src/core/libraries/ajm/ajm_at9.cpp +++ b/src/core/libraries/ajm/ajm_at9.cpp @@ -40,23 +40,11 @@ void AjmAt9Decoder::Initialize(const void* buffer, u32 buffer_size) { const auto params = reinterpret_cast(buffer); std::memcpy(m_config_data, params->config_data, ORBIS_AT9_CONFIG_DATA_SIZE); AjmAt9Decoder::Reset(); - m_pcm_buffer.resize(m_codec_info.frameSamples * m_codec_info.channels * GetPointCodeSize(), 0); + m_pcm_buffer.resize(m_codec_info.frameSamples * m_codec_info.channels * GetPCMSize(m_format), + 0); } -u8 AjmAt9Decoder::GetPointCodeSize() { - switch (m_format) { - case AjmFormatEncoding::S16: - return sizeof(s16); - case AjmFormatEncoding::S32: - return sizeof(s32); - case AjmFormatEncoding::Float: - return sizeof(float); - default: - UNREACHABLE(); - } -} - -void AjmAt9Decoder::GetInfo(void* out_info) { +void AjmAt9Decoder::GetInfo(void* out_info) const { auto* info = reinterpret_cast(out_info); info->super_frame_size = m_codec_info.superframeSize; info->frames_in_super_frame = m_codec_info.framesInSuperframe; @@ -65,8 +53,7 @@ void AjmAt9Decoder::GetInfo(void* out_info) { } std::tuple AjmAt9Decoder::ProcessData(std::span& in_buf, SparseOutputBuffer& output, - AjmSidebandGaplessDecode& gapless, - std::optional max_samples_per_channel) { + AjmInstanceGapless& gapless) { int ret = 0; int bytes_used = 0; switch (m_format) { @@ -91,32 +78,37 @@ std::tuple AjmAt9Decoder::ProcessData(std::span& in_buf, SparseOut m_superframe_bytes_remain -= bytes_used; - u32 skipped_samples = 0; - if (gapless.skipped_samples < gapless.skip_samples) { - skipped_samples = std::min(u32(m_codec_info.frameSamples), - u32(gapless.skip_samples - gapless.skipped_samples)); - gapless.skipped_samples += skipped_samples; + u32 skip_samples = 0; + if (gapless.current.skip_samples > 0) { + skip_samples = std::min(u16(m_codec_info.frameSamples), gapless.current.skip_samples); + gapless.current.skip_samples -= skip_samples; } - const auto max_samples = max_samples_per_channel.has_value() - ? max_samples_per_channel.value() * m_codec_info.channels - : std::numeric_limits::max(); + const auto max_pcm = gapless.init.total_samples != 0 + ? gapless.current.total_samples * m_codec_info.channels + : std::numeric_limits::max(); - size_t samples_written = 0; + size_t pcm_written = 0; switch (m_format) { case AjmFormatEncoding::S16: - samples_written = WriteOutputSamples(output, skipped_samples, max_samples); + pcm_written = WriteOutputSamples(output, skip_samples, max_pcm); break; case AjmFormatEncoding::S32: - samples_written = WriteOutputSamples(output, skipped_samples, max_samples); + pcm_written = WriteOutputSamples(output, skip_samples, max_pcm); break; case AjmFormatEncoding::Float: - samples_written = WriteOutputSamples(output, skipped_samples, max_samples); + pcm_written = WriteOutputSamples(output, skip_samples, max_pcm); break; default: UNREACHABLE(); } + const auto samples_written = pcm_written / m_codec_info.channels; + gapless.current.skipped_samples += m_codec_info.frameSamples - samples_written; + if (gapless.init.total_samples != 0) { + gapless.current.total_samples -= samples_written; + } + m_num_frames += 1; if ((m_num_frames % m_codec_info.framesInSuperframe) == 0) { if (m_superframe_bytes_remain) { @@ -126,18 +118,28 @@ std::tuple AjmAt9Decoder::ProcessData(std::span& in_buf, SparseOut m_num_frames = 0; } - return {1, samples_written / m_codec_info.channels}; + return {1, samples_written}; } -AjmSidebandFormat AjmAt9Decoder::GetFormat() { +AjmSidebandFormat AjmAt9Decoder::GetFormat() const { return AjmSidebandFormat{ .num_channels = u32(m_codec_info.channels), .channel_mask = GetChannelMask(u32(m_codec_info.channels)), .sampl_freq = u32(m_codec_info.samplingRate), .sample_encoding = m_format, - .bitrate = u32(m_codec_info.samplingRate * GetPointCodeSize() * 8), + .bitrate = u32((m_codec_info.samplingRate * m_codec_info.superframeSize * 8) / + (m_codec_info.framesInSuperframe * m_codec_info.frameSamples)), .reserved = 0, }; } +u32 AjmAt9Decoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const { + const auto max_samples = + gapless.init.total_samples != 0 + ? std::min(gapless.current.total_samples, u32(m_codec_info.frameSamples)) + : m_codec_info.frameSamples; + const auto skip_samples = std::min(u32(gapless.current.skip_samples), max_samples); + return (max_samples - skip_samples) * m_codec_info.channels * GetPCMSize(m_format); +} + } // namespace Libraries::Ajm diff --git a/src/core/libraries/ajm/ajm_at9.h b/src/core/libraries/ajm/ajm_at9.h index e5f65db93..689681dec 100644 --- a/src/core/libraries/ajm/ajm_at9.h +++ b/src/core/libraries/ajm/ajm_at9.h @@ -33,15 +33,13 @@ struct AjmAt9Decoder final : AjmCodec { void Reset() override; void Initialize(const void* buffer, u32 buffer_size) override; - void GetInfo(void* out_info) override; - AjmSidebandFormat GetFormat() override; + void GetInfo(void* out_info) const override; + AjmSidebandFormat GetFormat() const override; + u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override; std::tuple ProcessData(std::span& input, SparseOutputBuffer& output, - AjmSidebandGaplessDecode& gapless, - std::optional max_samples) override; + AjmInstanceGapless& gapless) override; private: - u8 GetPointCodeSize(); - template size_t WriteOutputSamples(SparseOutputBuffer& output, u32 skipped_samples, u32 max_samples) { std::span pcm_data{reinterpret_cast(m_pcm_buffer.data()), diff --git a/src/core/libraries/ajm/ajm_batch.cpp b/src/core/libraries/ajm/ajm_batch.cpp index 5c76beae8..b1cec88b3 100644 --- a/src/core/libraries/ajm/ajm_batch.cpp +++ b/src/core/libraries/ajm/ajm_batch.cpp @@ -135,7 +135,10 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { case Identifier::AjmIdentInputControlBuf: { ASSERT_MSG(!input_control_buffer.has_value(), "Only one instance of input control buffer is allowed per job"); - input_control_buffer = batch_buffer.Consume(); + const auto& buffer = batch_buffer.Consume(); + if (buffer.p_address != nullptr && buffer.size != 0) { + input_control_buffer = buffer; + } break; } case Identifier::AjmIdentControlFlags: @@ -155,19 +158,27 @@ AjmJob AjmJobFromBatchBuffer(u32 instance_id, AjmBatchBuffer batch_buffer) { case Identifier::AjmIdentInlineBuf: { ASSERT_MSG(!output_control_buffer.has_value(), "Only one instance of inline buffer is allowed per job"); - inline_buffer = batch_buffer.Consume(); + const auto& buffer = batch_buffer.Consume(); + if (buffer.p_address != nullptr && buffer.size != 0) { + inline_buffer = buffer; + } break; } case Identifier::AjmIdentOutputRunBuf: { auto& buffer = batch_buffer.Consume(); u8* p_begin = reinterpret_cast(buffer.p_address); - job.output.buffers.emplace_back(std::span(p_begin, p_begin + buffer.size)); + if (p_begin != nullptr && buffer.size != 0) { + job.output.buffers.emplace_back(std::span(p_begin, p_begin + buffer.size)); + } break; } case Identifier::AjmIdentOutputControlBuf: { ASSERT_MSG(!output_control_buffer.has_value(), "Only one instance of output control buffer is allowed per job"); - output_control_buffer = batch_buffer.Consume(); + const auto& buffer = batch_buffer.Consume(); + if (buffer.p_address != nullptr && buffer.size != 0) { + output_control_buffer = buffer; + } break; } default: diff --git a/src/core/libraries/ajm/ajm_instance.cpp b/src/core/libraries/ajm/ajm_instance.cpp index 85a6f54a1..4e04eea74 100644 --- a/src/core/libraries/ajm/ajm_instance.cpp +++ b/src/core/libraries/ajm/ajm_instance.cpp @@ -22,6 +22,19 @@ constexpr int ORBIS_AJM_RESULT_PRIORITY_PASSED = 0x00000200; constexpr int ORBIS_AJM_RESULT_CODEC_ERROR = 0x40000000; constexpr int ORBIS_AJM_RESULT_FATAL = 0x80000000; +u8 GetPCMSize(AjmFormatEncoding format) { + switch (format) { + case AjmFormatEncoding::S16: + return sizeof(s16); + case AjmFormatEncoding::S32: + return sizeof(s32); + case AjmFormatEncoding::Float: + return sizeof(float); + default: + UNREACHABLE(); + } +} + AjmInstance::AjmInstance(AjmCodecType codec_type, AjmInstanceFlags flags) : m_flags(flags) { switch (codec_type) { case AjmCodecType::At9Dec: { @@ -30,7 +43,8 @@ AjmInstance::AjmInstance(AjmCodecType codec_type, AjmInstanceFlags flags) : m_fl break; } case AjmCodecType::Mp3Dec: { - m_codec = std::make_unique(AjmFormatEncoding(flags.format)); + m_codec = std::make_unique(AjmFormatEncoding(flags.format), + AjmMp3CodecFlags(flags.codec)); break; } default: @@ -45,7 +59,6 @@ void AjmInstance::ExecuteJob(AjmJob& job) { m_format = {}; m_gapless = {}; m_resample_parameters = {}; - m_gapless_samples = 0; m_total_samples = 0; m_codec->Reset(); } @@ -64,27 +77,47 @@ void AjmInstance::ExecuteJob(AjmJob& job) { } if (job.input.gapless_decode.has_value()) { auto& params = job.input.gapless_decode.value(); - m_gapless.total_samples = params.total_samples; - m_gapless.skip_samples = params.skip_samples; + if (params.total_samples != 0) { + const auto max = std::max(params.total_samples, m_gapless.init.total_samples); + m_gapless.current.total_samples += max - m_gapless.init.total_samples; + m_gapless.init.total_samples = max; + } + if (params.skip_samples != 0) { + const auto max = std::max(params.skip_samples, m_gapless.init.skip_samples); + m_gapless.current.skip_samples += max - m_gapless.init.skip_samples; + m_gapless.init.skip_samples = max; + } } if (!job.input.buffer.empty() && !job.output.buffers.empty()) { - u32 frames_decoded = 0; std::span in_buf(job.input.buffer); SparseOutputBuffer out_buf(job.output.buffers); + u32 frames_decoded = 0; auto in_size = in_buf.size(); auto out_size = out_buf.Size(); - while (!in_buf.empty() && !out_buf.IsEmpty() && !IsGaplessEnd()) { - const auto samples_remain = - m_gapless.total_samples != 0 - ? std::optional{m_gapless.total_samples - m_gapless_samples} - : std::optional{}; - const auto [nframes, nsamples] = - m_codec->ProcessData(in_buf, out_buf, m_gapless, samples_remain); + while (!in_buf.empty() && !out_buf.IsEmpty() && !m_gapless.IsEnd()) { + if (!HasEnoughSpace(out_buf)) { + if (job.output.p_mframe == nullptr || frames_decoded == 0) { + job.output.p_result->result = ORBIS_AJM_RESULT_NOT_ENOUGH_ROOM; + break; + } + } + + const auto [nframes, nsamples] = m_codec->ProcessData(in_buf, out_buf, m_gapless); frames_decoded += nframes; m_total_samples += nsamples; - m_gapless_samples += nsamples; + + if (False(job.flags.run_flags & AjmJobRunFlags::MultipleFrames)) { + break; + } + } + + if (m_gapless.IsEnd()) { + in_buf = in_buf.subspan(in_buf.size()); + m_gapless.current.total_samples = m_gapless.init.total_samples; + m_gapless.current.skip_samples = m_gapless.init.skip_samples; + m_codec->Reset(); } if (job.output.p_mframe) { job.output.p_mframe->num_frames = frames_decoded; @@ -96,25 +129,19 @@ void AjmInstance::ExecuteJob(AjmJob& job) { } } - if (m_flags.gapless_loop && m_gapless.total_samples != 0 && - m_gapless_samples >= m_gapless.total_samples) { - m_gapless_samples = 0; - m_gapless.skipped_samples = 0; - m_codec->Reset(); - } if (job.output.p_format != nullptr) { *job.output.p_format = m_codec->GetFormat(); } if (job.output.p_gapless_decode != nullptr) { - *job.output.p_gapless_decode = m_gapless; + *job.output.p_gapless_decode = m_gapless.current; } if (job.output.p_codec_info != nullptr) { m_codec->GetInfo(job.output.p_codec_info); } } -bool AjmInstance::IsGaplessEnd() { - return m_gapless.total_samples != 0 && m_gapless_samples >= m_gapless.total_samples; +bool AjmInstance::HasEnoughSpace(const SparseOutputBuffer& output) const { + return output.Size() >= m_codec->GetNextFrameSize(m_gapless); } } // namespace Libraries::Ajm diff --git a/src/core/libraries/ajm/ajm_instance.h b/src/core/libraries/ajm/ajm_instance.h index d1d398ae8..9d0f6b9f3 100644 --- a/src/core/libraries/ajm/ajm_instance.h +++ b/src/core/libraries/ajm/ajm_instance.h @@ -14,6 +14,8 @@ namespace Libraries::Ajm { +u8 GetPCMSize(AjmFormatEncoding format); + class SparseOutputBuffer { public: SparseOutputBuffer(std::span> chunks) @@ -33,14 +35,17 @@ public: ++m_current; } } + if (!pcm.empty()) { + LOG_ERROR(Lib_Ajm, "Could not write {} samples", pcm.size()); + } return samples_written; } - bool IsEmpty() { + bool IsEmpty() const { return m_current == m_chunks.end(); } - size_t Size() { + size_t Size() const { size_t result = 0; for (auto it = m_current; it != m_chunks.end(); ++it) { result += it->size(); @@ -53,17 +58,26 @@ private: std::span>::iterator m_current; }; +struct AjmInstanceGapless { + AjmSidebandGaplessDecode init{}; + AjmSidebandGaplessDecode current{}; + + bool IsEnd() const { + return init.total_samples != 0 && current.total_samples == 0; + } +}; + class AjmCodec { public: virtual ~AjmCodec() = default; virtual void Initialize(const void* buffer, u32 buffer_size) = 0; virtual void Reset() = 0; - virtual void GetInfo(void* out_info) = 0; - virtual AjmSidebandFormat GetFormat() = 0; + virtual void GetInfo(void* out_info) const = 0; + virtual AjmSidebandFormat GetFormat() const = 0; + virtual u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const = 0; virtual std::tuple ProcessData(std::span& input, SparseOutputBuffer& output, - AjmSidebandGaplessDecode& gapless, - std::optional max_samples_per_channel) = 0; + AjmInstanceGapless& gapless) = 0; }; class AjmInstance { @@ -73,16 +87,14 @@ public: void ExecuteJob(AjmJob& job); private: - bool IsGaplessEnd(); + bool HasEnoughSpace(const SparseOutputBuffer& output) const; + std::optional GetNumRemainingSamples() const; AjmInstanceFlags m_flags{}; AjmSidebandFormat m_format{}; - AjmSidebandGaplessDecode m_gapless{}; + AjmInstanceGapless m_gapless{}; AjmSidebandResampleParameters m_resample_parameters{}; - - u32 m_gapless_samples{}; u32 m_total_samples{}; - std::unique_ptr m_codec; }; diff --git a/src/core/libraries/ajm/ajm_mp3.cpp b/src/core/libraries/ajm/ajm_mp3.cpp index 90196bb91..3b464238d 100644 --- a/src/core/libraries/ajm/ajm_mp3.cpp +++ b/src/core/libraries/ajm/ajm_mp3.cpp @@ -15,18 +15,50 @@ extern "C" { namespace Libraries::Ajm { // Following tables have been reversed from AJM library -static constexpr std::array, 3> SamplerateTable = {{ - {0x5622, 0x5DC0, 0x3E80}, - {0xAC44, 0xBB80, 0x7D00}, - {0x2B11, 0x2EE0, 0x1F40}, -}}; +static constexpr std::array, 4> Mp3SampleRateTable = { + std::array{11025, 12000, 8000, 0}, + std::array{0, 0, 0, 0}, + std::array{22050, 24000, 16000, 0}, + std::array{44100, 48000, 32000, 0}, +}; -static constexpr std::array, 2> BitrateTable = {{ - {0, 0x20, 0x28, 0x30, 0x38, 0x40, 0x50, 0x60, 0x70, 0x80, 0xA0, 0xC0, 0xE0, 0x100, 0x140}, - {0, 0x8, 0x10, 0x18, 0x20, 0x28, 0x30, 0x38, 0x40, 0x50, 0x60, 0x70, 0x80, 0x90, 0xA0}, -}}; +static constexpr std::array, 4> Mp3BitRateTable = { + std::array{0, 8, 16, 24, 32, 40, 48, 56, 64, 0, 0, 0, 0, 0, 0, 0}, + std::array{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + std::array{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0}, + std::array{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0}, +}; -static constexpr std::array UnkTable = {0x48, 0x90}; +enum class Mp3AudioVersion : u32 { + V2_5 = 0, + Reserved = 1, + V2 = 2, + V1 = 3, +}; + +enum class Mp3ChannelMode : u32 { + Stereo = 0, + JointStereo = 1, + DualChannel = 2, + SingleChannel = 3, +}; + +struct Mp3Header { + u32 emphasis : 2; + u32 original : 1; + u32 copyright : 1; + u32 mode_ext_idx : 2; + Mp3ChannelMode channel_mode : 2; + u32 : 1; + u32 padding : 1; + u32 sampling_rate_idx : 2; + u32 bitrate_idx : 4; + u32 protection_type : 1; + u32 layer_type : 2; + Mp3AudioVersion version : 2; + u32 sync : 11; +}; +static_assert(sizeof(Mp3Header) == sizeof(u32)); static AVSampleFormat AjmToAVSampleFormat(AjmFormatEncoding format) { switch (format) { @@ -62,7 +94,7 @@ AVFrame* AjmMp3Decoder::ConvertAudioFrame(AVFrame* frame) { swr_init(m_swr_context); const auto res = swr_convert_frame(m_swr_context, new_frame, frame); if (res < 0) { - LOG_ERROR(Lib_AvPlayer, "Could not convert to S16: {}", av_err2str(res)); + LOG_ERROR(Lib_AvPlayer, "Could not convert frame: {}", av_err2str(res)); av_frame_free(&new_frame); av_frame_free(&frame); return nullptr; @@ -71,48 +103,57 @@ AVFrame* AjmMp3Decoder::ConvertAudioFrame(AVFrame* frame) { return new_frame; } -AjmMp3Decoder::AjmMp3Decoder(AjmFormatEncoding format) - : m_format(format), m_codec(avcodec_find_decoder(AV_CODEC_ID_MP3)), - m_parser(av_parser_init(m_codec->id)) { - AjmMp3Decoder::Reset(); -} - -AjmMp3Decoder::~AjmMp3Decoder() { - swr_free(&m_swr_context); - avcodec_free_context(&m_codec_context); -} - -void AjmMp3Decoder::Reset() { - if (m_codec_context) { - avcodec_free_context(&m_codec_context); - } - m_codec_context = avcodec_alloc_context3(m_codec); - ASSERT_MSG(m_codec_context, "Could not allocate audio m_codec context"); +AjmMp3Decoder::AjmMp3Decoder(AjmFormatEncoding format, AjmMp3CodecFlags flags) + : m_format(format), m_flags(flags), m_codec(avcodec_find_decoder(AV_CODEC_ID_MP3)), + m_codec_context(avcodec_alloc_context3(m_codec)), m_parser(av_parser_init(m_codec->id)) { int ret = avcodec_open2(m_codec_context, m_codec, nullptr); ASSERT_MSG(ret >= 0, "Could not open m_codec"); } -void AjmMp3Decoder::GetInfo(void* out_info) { +AjmMp3Decoder::~AjmMp3Decoder() { + swr_free(&m_swr_context); + av_parser_close(m_parser); + avcodec_free_context(&m_codec_context); +} + +void AjmMp3Decoder::Reset() { + avcodec_flush_buffers(m_codec_context); + m_header.reset(); + m_frame_samples = 0; +} + +void AjmMp3Decoder::GetInfo(void* out_info) const { auto* info = reinterpret_cast(out_info); + if (m_header.has_value()) { + auto* header = reinterpret_cast(&m_header.value()); + info->header = std::byteswap(m_header.value()); + info->has_crc = header->protection_type; + info->channel_mode = static_cast(header->channel_mode); + info->mode_extension = header->mode_ext_idx; + info->copyright = header->copyright; + info->original = header->original; + info->emphasis = header->emphasis; + } } std::tuple AjmMp3Decoder::ProcessData(std::span& in_buf, SparseOutputBuffer& output, - AjmSidebandGaplessDecode& gapless, - std::optional max_samples_per_channel) { + AjmInstanceGapless& gapless) { AVPacket* pkt = av_packet_alloc(); + if ((!m_header.has_value() || m_frame_samples == 0) && in_buf.size() >= 4) { + m_header = std::byteswap(*reinterpret_cast(in_buf.data())); + AjmDecMp3ParseFrame info{}; + ParseMp3Header(in_buf.data(), in_buf.size(), false, &info); + m_frame_samples = info.samples_per_channel; + } + int ret = av_parser_parse2(m_parser, m_codec_context, &pkt->data, &pkt->size, in_buf.data(), in_buf.size(), AV_NOPTS_VALUE, AV_NOPTS_VALUE, 0); ASSERT_MSG(ret >= 0, "Error while parsing {}", ret); in_buf = in_buf.subspan(ret); u32 frames_decoded = 0; - u32 samples_decoded = 0; - - auto max_samples = - max_samples_per_channel.has_value() - ? max_samples_per_channel.value() * m_codec_context->ch_layout.nb_channels - : std::numeric_limits::max(); + u32 samples_written = 0; if (pkt->size) { // Send the packet with the compressed data to the decoder @@ -135,31 +176,38 @@ std::tuple AjmMp3Decoder::ProcessData(std::span& in_buf, SparseOut frame = ConvertAudioFrame(frame); frames_decoded += 1; - u32 skipped_samples = 0; - if (gapless.skipped_samples < gapless.skip_samples) { - skipped_samples = std::min(u32(frame->nb_samples), - u32(gapless.skip_samples - gapless.skipped_samples)); - gapless.skipped_samples += skipped_samples; + u32 skip_samples = 0; + if (gapless.current.skip_samples > 0) { + skip_samples = std::min(u16(frame->nb_samples), gapless.current.skip_samples); + gapless.current.skip_samples -= skip_samples; } + const auto max_pcm = + gapless.init.total_samples != 0 + ? gapless.current.total_samples * m_codec_context->ch_layout.nb_channels + : std::numeric_limits::max(); + + u32 pcm_written = 0; switch (m_format) { case AjmFormatEncoding::S16: - samples_decoded += - WriteOutputSamples(frame, output, skipped_samples, max_samples); + pcm_written = WriteOutputPCM(frame, output, skip_samples, max_pcm); break; case AjmFormatEncoding::S32: - samples_decoded += - WriteOutputSamples(frame, output, skipped_samples, max_samples); + pcm_written = WriteOutputPCM(frame, output, skip_samples, max_pcm); break; case AjmFormatEncoding::Float: - samples_decoded += - WriteOutputSamples(frame, output, skipped_samples, max_samples); + pcm_written = WriteOutputPCM(frame, output, skip_samples, max_pcm); break; default: UNREACHABLE(); } - max_samples -= samples_decoded; + const auto samples = pcm_written / m_codec_context->ch_layout.nb_channels; + samples_written += samples; + gapless.current.skipped_samples += frame->nb_samples - samples; + if (gapless.init.total_samples != 0) { + gapless.current.total_samples -= samples; + } av_frame_free(&frame); } @@ -167,38 +215,221 @@ std::tuple AjmMp3Decoder::ProcessData(std::span& in_buf, SparseOut av_packet_free(&pkt); - return {frames_decoded, samples_decoded}; + return {frames_decoded, samples_written}; } -int AjmMp3Decoder::ParseMp3Header(const u8* buf, u32 stream_size, int parse_ofl, +u32 AjmMp3Decoder::GetNextFrameSize(const AjmInstanceGapless& gapless) const { + const auto max_samples = gapless.init.total_samples != 0 + ? std::min(gapless.current.total_samples, m_frame_samples) + : m_frame_samples; + const auto skip_samples = std::min(u32(gapless.current.skip_samples), max_samples); + return (max_samples - skip_samples) * m_codec_context->ch_layout.nb_channels * + GetPCMSize(m_format); +} + +class BitReader { +public: + BitReader(const u8* data) : m_data(data) {} + + template + T Read(u32 const nbits) { + T accumulator = 0; + for (unsigned i = 0; i < nbits; ++i) { + accumulator = (accumulator << 1) + GetBit(); + } + return accumulator; + } + + void Skip(size_t nbits) { + m_bit_offset += nbits; + } + + size_t GetCurrentOffset() { + return m_bit_offset; + } + +private: + u8 GetBit() { + const auto bit = (m_data[m_bit_offset / 8] >> (7 - (m_bit_offset % 8))) & 1; + m_bit_offset += 1; + return bit; + } + + const u8* m_data; + size_t m_bit_offset = 0; +}; + +int AjmMp3Decoder::ParseMp3Header(const u8* p_begin, u32 stream_size, int parse_ofl, AjmDecMp3ParseFrame* frame) { LOG_INFO(Lib_Ajm, "called stream_size = {} parse_ofl = {}", stream_size, parse_ofl); - if (buf == nullptr || stream_size < 4 || frame == nullptr) { - return ORBIS_AJM_ERROR_INVALID_PARAMETER; - } - if ((buf[0] & SYNCWORDH) != SYNCWORDH || (buf[1] & SYNCWORDL) != SYNCWORDL) { + + if (p_begin == nullptr || stream_size < 4 || frame == nullptr) { return ORBIS_AJM_ERROR_INVALID_PARAMETER; } - const u32 unk_idx = buf[1] >> 3 & 1; - const s32 version_idx = (buf[1] >> 3 & 3) ^ 2; - const s32 sr_idx = buf[2] >> 2 & 3; - const s32 br_idx = (buf[2] >> 4) & 0xf; - const s32 padding_bit = (buf[2] >> 1) & 0x1; + const auto* p_current = p_begin; + + auto bytes = std::byteswap(*reinterpret_cast(p_current)); + p_current += 4; + auto header = reinterpret_cast(&bytes); + if (header->sync != 0x7FF) { + return ORBIS_AJM_ERROR_INVALID_PARAMETER; + } + + frame->sample_rate = Mp3SampleRateTable[u32(header->version)][header->sampling_rate_idx]; + frame->bitrate = Mp3BitRateTable[u32(header->version)][header->bitrate_idx] * 1000; + frame->num_channels = header->channel_mode == Mp3ChannelMode::SingleChannel ? 1 : 2; + if (header->version == Mp3AudioVersion::V1) { + frame->frame_size = (144 * frame->bitrate) / frame->sample_rate + header->padding; + frame->samples_per_channel = 1152; + } else { + frame->frame_size = (72 * frame->bitrate) / frame->sample_rate + header->padding; + frame->samples_per_channel = 576; + } - frame->sample_rate = SamplerateTable[version_idx][sr_idx]; - frame->bitrate = BitrateTable[version_idx != 1][br_idx] * 1000; - frame->num_channels = (buf[3] < 0xc0) + 1; - frame->frame_size = (UnkTable[unk_idx] * frame->bitrate) / frame->sample_rate + padding_bit; - frame->samples_per_channel = UnkTable[unk_idx] * 8; frame->encoder_delay = 0; + frame->num_frames = 0; + frame->total_samples = 0; + frame->ofl_type = AjmDecMp3OflType::None; + + if (!parse_ofl) { + return ORBIS_OK; + } + + BitReader reader(p_current); + if (header->protection_type == 0) { + reader.Skip(16); // crc = reader.Read(16); + } + + if (header->version == Mp3AudioVersion::V1) { + // main_data_begin = reader.Read(9); + // if (header->channel_mode == Mp3ChannelMode::SingleChannel) { + // private_bits = reader.Read(5); + // } else { + // private_bits = reader.Read(3); + // } + // for (u32 ch = 0; ch < frame->num_channels; ++ch) { + // for (u8 band = 0; band < 4; ++band) { + // scfsi[ch][band] = reader.Read(1); + // } + // } + if (header->channel_mode == Mp3ChannelMode::SingleChannel) { + reader.Skip(18); + } else { + reader.Skip(20); + } + } else { + // main_data_begin = reader.Read(8); + // if (header->channel_mode == Mp3ChannelMode::SingleChannel) { + // private_bits = reader.Read(1); + // } else { + // private_bits = reader.Read(2); + // } + if (header->channel_mode == Mp3ChannelMode::SingleChannel) { + reader.Skip(9); + } else { + reader.Skip(10); + } + } + + u32 part2_3_length = 0; + // Number of granules (18x32 sub-band samples) + const u8 ngr = header->version == Mp3AudioVersion::V1 ? 2 : 1; + for (u8 gr = 0; gr < ngr; ++gr) { + for (u32 ch = 0; ch < frame->num_channels; ++ch) { + // part2_3_length[gr][ch] = reader.Read(12); + part2_3_length += reader.Read(12); + // big_values[gr][ch] = reader.Read(9); + // global_main[gr][ch] = reader.Read(8); + // if (header->version == Mp3AudioVersion::V1) { + // scalefac_compress[gr][ch] = reader.Read(4); + // } else { + // scalefac_compress[gr][ch] = reader.Read(9); + // } + // window_switching_flag = reader.Read(1); + // if (window_switching_flag) { + // block_type[gr][ch] = reader.Read(2); + // mixed_block_flag[gr][ch] = reader.Read(1); + // for (u8 region = 0; region < 2; ++region) { + // table_select[gr][ch][region] = reader.Read(5); + // } + // for (u8 window = 0; window < 3; ++window) { + // subblock_gain[gr][ch][window] = reader.Read(3); + // } + // } else { + // for (u8 region = 0; region < 3; ++region) { + // table_select[gr][ch][region] = reader.Read(5); + // } + // region0_count[gr][ch] = reader.Read(4); + // region1_count[gr][ch] = reader.Read(3); + // } + // if (header->version == Mp3AudioVersion::V1) { + // preflag[gr][ch] = reader.Read(1); + // } + // scalefac_scale[gr][ch] = reader.Read(1); + // count1table_select[gr][ch] = reader.Read(1); + if (header->version == Mp3AudioVersion::V1) { + reader.Skip(47); + } else { + reader.Skip(51); + } + } + } + reader.Skip(part2_3_length); + + p_current += ((reader.GetCurrentOffset() + 7) / 8); + + const auto* p_end = p_begin + frame->frame_size; + if (memcmp(p_current, "Xing", 4) == 0 || memcmp(p_current, "Info", 4) == 0) { + // TODO: Parse Xing/Lame header + LOG_ERROR(Lib_Ajm, "Xing/Lame header is not implemented."); + } else if (memcmp(p_current, "VBRI", 4) == 0) { + // TODO: Parse VBRI header + LOG_ERROR(Lib_Ajm, "VBRI header is not implemented."); + } else { + // Parse FGH header + constexpr auto fgh_indicator = 0xB4; + while ((p_current + 9) < p_end && *p_current != fgh_indicator) { + ++p_current; + } + auto p_fgh = p_current; + if ((p_current + 9) < p_end && *p_current == fgh_indicator) { + u8 crc = 0xFF; + auto crc_func = [](u8 c, u8 v, u8 s) { + if (((c >> 7) & 1) != ((v >> s) & 1)) { + return c * 2; + } + return (c * 2) ^ 0x45; + }; + for (u8 i = 0; i < 9; ++i, ++p_current) { + for (u8 j = 0; j < 8; ++j) { + crc = crc_func(crc, *p_current, 7 - j); + } + } + if (p_fgh[9] == crc) { + frame->encoder_delay = std::byteswap(*reinterpret_cast(p_fgh + 1)); + frame->total_samples = std::byteswap(*reinterpret_cast(p_fgh + 3)); + frame->ofl_type = AjmDecMp3OflType::Fgh; + } else { + LOG_ERROR(Lib_Ajm, "FGH header CRC is incorrect."); + } + } else { + LOG_ERROR(Lib_Ajm, "Could not find vendor header."); + } + } return ORBIS_OK; } -AjmSidebandFormat AjmMp3Decoder::GetFormat() { - LOG_ERROR(Lib_Ajm, "Unimplemented"); - return AjmSidebandFormat{}; +AjmSidebandFormat AjmMp3Decoder::GetFormat() const { + return AjmSidebandFormat{ + .num_channels = u32(m_codec_context->ch_layout.nb_channels), + .channel_mask = GetChannelMask(u32(m_codec_context->ch_layout.nb_channels)), + .sampl_freq = u32(m_codec_context->sample_rate), + .sample_encoding = m_format, + .bitrate = u32(m_codec_context->bit_rate), + .reserved = 0, + }; }; } // namespace Libraries::Ajm diff --git a/src/core/libraries/ajm/ajm_mp3.h b/src/core/libraries/ajm/ajm_mp3.h index b5da19e77..70c949550 100644 --- a/src/core/libraries/ajm/ajm_mp3.h +++ b/src/core/libraries/ajm/ajm_mp3.h @@ -13,7 +13,19 @@ struct SwrContext; namespace Libraries::Ajm { -enum class AjmDecMp3OflType : u32 { None = 0, Lame = 1, Vbri = 2, Fgh = 3, VbriAndFgh = 4 }; +enum class AjmDecMp3OflType : u32 { + None = 0, + Lame = 1, + Vbri = 2, + Fgh = 3, + VbriAndFgh = 4, +}; + +enum AjmMp3CodecFlags : u32 { + IgnoreOfl = 1 << 0, + VlcRewind = 1 << 8, +}; +DECLARE_ENUM_FLAG_OPERATORS(AjmMp3CodecFlags) // 11-bit syncword if MPEG 2.5 extensions are enabled static constexpr u8 SYNCWORDH = 0xff; @@ -51,39 +63,40 @@ struct AjmSidebandDecMp3CodecInfo { class AjmMp3Decoder : public AjmCodec { public: - explicit AjmMp3Decoder(AjmFormatEncoding format); + explicit AjmMp3Decoder(AjmFormatEncoding format, AjmMp3CodecFlags flags); ~AjmMp3Decoder() override; void Reset() override; void Initialize(const void* buffer, u32 buffer_size) override {} - void GetInfo(void* out_info) override; - AjmSidebandFormat GetFormat() override; + void GetInfo(void* out_info) const override; + AjmSidebandFormat GetFormat() const override; + u32 GetNextFrameSize(const AjmInstanceGapless& gapless) const override; std::tuple ProcessData(std::span& input, SparseOutputBuffer& output, - AjmSidebandGaplessDecode& gapless, - std::optional max_samples_per_channel) override; + AjmInstanceGapless& gapless) override; static int ParseMp3Header(const u8* buf, u32 stream_size, int parse_ofl, AjmDecMp3ParseFrame* frame); private: template - size_t WriteOutputSamples(AVFrame* frame, SparseOutputBuffer& output, u32 skipped_samples, - u32 max_samples) { - const auto size = frame->ch_layout.nb_channels * frame->nb_samples * sizeof(T); - std::span pcm_data(reinterpret_cast(frame->data[0]), size >> 1); + size_t WriteOutputPCM(AVFrame* frame, SparseOutputBuffer& output, u32 skipped_samples, + u32 max_pcm) { + std::span pcm_data(reinterpret_cast(frame->data[0]), + frame->nb_samples * frame->ch_layout.nb_channels); pcm_data = pcm_data.subspan(skipped_samples * frame->ch_layout.nb_channels); - const auto pcm_size = std::min(u32(pcm_data.size()), max_samples); - const auto samples_written = output.Write(pcm_data.subspan(0, pcm_size)); - return samples_written / frame->ch_layout.nb_channels; + return output.Write(pcm_data.subspan(0, std::min(u32(pcm_data.size()), max_pcm))); } AVFrame* ConvertAudioFrame(AVFrame* frame); const AjmFormatEncoding m_format; + const AjmMp3CodecFlags m_flags; const AVCodec* m_codec = nullptr; AVCodecContext* m_codec_context = nullptr; AVCodecParserContext* m_parser = nullptr; SwrContext* m_swr_context = nullptr; + std::optional m_header; + u32 m_frame_samples = 0; }; } // namespace Libraries::Ajm From 7be35c399751c65e9d824c7b47cff802d60785cb Mon Sep 17 00:00:00 2001 From: Osyotr Date: Thu, 14 Nov 2024 13:01:33 +0300 Subject: [PATCH 09/11] Save config in UTF-8 (#1524) --- src/common/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/config.cpp b/src/common/config.cpp index 1dde7223c..e97a46005 100644 --- a/src/common/config.cpp +++ b/src/common/config.cpp @@ -658,7 +658,7 @@ void save(const std::filesystem::path& path) { // TODO Migration code, after a major release this should be removed. data.at("GUI").as_table().erase("installDir"); - std::ofstream file(path, std::ios::out); + std::ofstream file(path, std::ios::binary); file << data; file.close(); } From ce158290fbd7871a3f890323501e6fe3e8bec832 Mon Sep 17 00:00:00 2001 From: Stephen Miller <56742918+StevenMiller123@users.noreply.github.com> Date: Thu, 14 Nov 2024 10:00:57 -0600 Subject: [PATCH 10/11] Minor Kernel Fixes (#1529) * Skip destruction of adaptive mutex initializers Based around similar behaviors implemented in the more-kernel branch. Hatsune Miku Project Diva X needs this. * Fix posix_lseek result overflow Seen when testing Spider-Man Miles Morales on more-kernel. * Add posix_fsync Used by Spider-Man Miles Morales. I've added the normal posix error handling to this function, though I'm aware sceKernelFsync doesn't return any errors currently. This is for future proofing and accuracy, as the actual libkernel does the usual error handling too. * Properly handle VirtualQuery calls on PoolReserved memory. * Export posix_getpagesize under libkernel Bloons TD 5 needs this. * Clang --- src/core/libraries/kernel/file_system.cpp | 14 +++++++++++++- src/core/libraries/kernel/libkernel.cpp | 1 + src/core/libraries/kernel/thread_management.cpp | 4 ++++ src/core/memory.cpp | 3 ++- 4 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/core/libraries/kernel/file_system.cpp b/src/core/libraries/kernel/file_system.cpp index 7f86ee540..e6b657c3a 100644 --- a/src/core/libraries/kernel/file_system.cpp +++ b/src/core/libraries/kernel/file_system.cpp @@ -237,7 +237,7 @@ s64 PS4_SYSV_ABI sceKernelLseek(int d, s64 offset, int whence) { } s64 PS4_SYSV_ABI posix_lseek(int d, s64 offset, int whence) { - int result = sceKernelLseek(d, offset, whence); + s64 result = sceKernelLseek(d, offset, whence); if (result < 0) { LOG_ERROR(Kernel_Pthread, "posix_lseek: error = {}", result); ErrSceToPosix(result); @@ -490,6 +490,16 @@ s32 PS4_SYSV_ABI sceKernelFsync(int fd) { return ORBIS_OK; } +s32 PS4_SYSV_ABI posix_fsync(int fd) { + s32 result = sceKernelFsync(fd); + if (result < 0) { + LOG_ERROR(Kernel_Pthread, "posix_fstat: error = {}", result); + ErrSceToPosix(result); + return -1; + } + return result; +} + int PS4_SYSV_ABI sceKernelFtruncate(int fd, s64 length) { auto* h = Common::Singleton::Instance(); auto* file = h->GetFile(fd); @@ -642,6 +652,8 @@ void fileSystemSymbolsRegister(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("+r3rMFwItV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPread); LIB_FUNCTION("uWyW3v98sU4", "libkernel", 1, "libkernel", 1, 1, sceKernelCheckReachability); LIB_FUNCTION("fTx66l5iWIA", "libkernel", 1, "libkernel", 1, 1, sceKernelFsync); + LIB_FUNCTION("juWbTNM+8hw", "libkernel", 1, "libkernel", 1, 1, posix_fsync); + LIB_FUNCTION("juWbTNM+8hw", "libScePosix", 1, "libkernel", 1, 1, posix_fsync); LIB_FUNCTION("j2AIqSqJP0w", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdents); LIB_FUNCTION("taRWhTJFTgE", "libkernel", 1, "libkernel", 1, 1, sceKernelGetdirentries); LIB_FUNCTION("nKWi-N2HBV4", "libkernel", 1, "libkernel", 1, 1, sceKernelPwrite); diff --git a/src/core/libraries/kernel/libkernel.cpp b/src/core/libraries/kernel/libkernel.cpp index c621b4bca..b3eb81ec8 100644 --- a/src/core/libraries/kernel/libkernel.cpp +++ b/src/core/libraries/kernel/libkernel.cpp @@ -491,6 +491,7 @@ void LibKernel_Register(Core::Loader::SymbolsResolver* sym) { LIB_FUNCTION("-o5uEDpN+oY", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertUtcToLocaltime); LIB_FUNCTION("WB66evu8bsU", "libkernel", 1, "libkernel", 1, 1, sceKernelGetCompiledSdkVersion); LIB_FUNCTION("DRuBt2pvICk", "libkernel", 1, "libkernel", 1, 1, ps4__read); + LIB_FUNCTION("k+AXqu2-eBc", "libkernel", 1, "libkernel", 1, 1, posix_getpagesize); LIB_FUNCTION("k+AXqu2-eBc", "libScePosix", 1, "libkernel", 1, 1, posix_getpagesize); Libraries::Kernel::fileSystemSymbolsRegister(sym); diff --git a/src/core/libraries/kernel/thread_management.cpp b/src/core/libraries/kernel/thread_management.cpp index 39c0eaf80..85f618090 100644 --- a/src/core/libraries/kernel/thread_management.cpp +++ b/src/core/libraries/kernel/thread_management.cpp @@ -477,6 +477,10 @@ int PS4_SYSV_ABI scePthreadMutexDestroy(ScePthreadMutex* mutex) { return SCE_KERNEL_ERROR_EINVAL; } + if (*mutex == ORBIS_PTHREAD_MUTEX_ADAPTIVE_INITIALIZER) { + return ORBIS_OK; + } + int result = pthread_mutex_destroy(&(*mutex)->pth_mutex); LOG_DEBUG(Kernel_Pthread, "name={}, result={}", (*mutex)->name, result); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 031b7b135..61eb421e5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -514,7 +514,8 @@ int MemoryManager::VirtualQuery(VAddr addr, int flags, info->is_direct.Assign(vma.type == VMAType::Direct); info->is_stack.Assign(vma.type == VMAType::Stack); info->is_pooled.Assign(vma.type == VMAType::Pooled); - info->is_committed.Assign(vma.type != VMAType::Free && vma.type != VMAType::Reserved); + info->is_committed.Assign(vma.type != VMAType::Free && vma.type != VMAType::Reserved && + vma.type != VMAType::PoolReserved); vma.name.copy(info->name.data(), std::min(info->name.size(), vma.name.size())); if (vma.type == VMAType::Direct) { const auto dmem_it = FindDmemArea(vma.phys_base); From e1fecda74fe4fa5263157f6364835c1d0c3396fc Mon Sep 17 00:00:00 2001 From: Vladislav Mikhalin Date: Sat, 16 Nov 2024 20:17:43 +0300 Subject: [PATCH 11/11] Fix depth bias (#1538) --- src/video_core/renderer_vulkan/vk_rasterizer.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 212b8165f..6d214a18e 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -393,14 +393,12 @@ void Rasterizer::UpdateDynamicState(const GraphicsPipeline& pipeline) { if (regs.depth_control.depth_bounds_enable) { cmdbuf.setDepthBounds(regs.depth_bounds_min, regs.depth_bounds_max); } - if (regs.polygon_control.NeedsBias()) { - if (regs.polygon_control.enable_polygon_offset_front) { - cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias, - regs.poly_offset.front_scale); - } else { - cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias, - regs.poly_offset.back_scale); - } + if (regs.polygon_control.enable_polygon_offset_front) { + cmdbuf.setDepthBias(regs.poly_offset.front_offset, regs.poly_offset.depth_bias, + regs.poly_offset.front_scale / 16.f); + } else if (regs.polygon_control.enable_polygon_offset_back) { + cmdbuf.setDepthBias(regs.poly_offset.back_offset, regs.poly_offset.depth_bias, + regs.poly_offset.back_scale / 16.f); } if (regs.depth_control.stencil_enable) { const auto front = regs.stencil_ref_front;