Merge branch 'shadps4-emu:main' into allocate-fixes

This commit is contained in:
Stephen Miller 2025-01-23 16:01:47 -06:00 committed by GitHub
commit 5d3e2d80b6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
145 changed files with 4255 additions and 1412 deletions

View File

@ -390,7 +390,7 @@ jobs:
- name: Cache CMake Configuration - name: Cache CMake Configuration
uses: actions/cache@v4 uses: actions/cache@v4
env: env:
cache-name: ${{ runner.os }}-sdl-cache-cmake-configuration cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-configuration
with: with:
path: | path: |
${{github.workspace}}/build ${{github.workspace}}/build
@ -401,7 +401,7 @@ jobs:
- name: Cache CMake Build - name: Cache CMake Build
uses: hendrikmuhs/ccache-action@v1.2.14 uses: hendrikmuhs/ccache-action@v1.2.14
env: env:
cache-name: ${{ runner.os }}-sdl-cache-cmake-build cache-name: ${{ runner.os }}-sdl-gcc-cache-cmake-build
with: with:
append-timestamp: false append-timestamp: false
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}
@ -426,7 +426,7 @@ jobs:
- name: Cache CMake Configuration - name: Cache CMake Configuration
uses: actions/cache@v4 uses: actions/cache@v4
env: env:
cache-name: ${{ runner.os }}-qt-cache-cmake-configuration cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-configuration
with: with:
path: | path: |
${{github.workspace}}/build ${{github.workspace}}/build
@ -437,7 +437,7 @@ jobs:
- name: Cache CMake Build - name: Cache CMake Build
uses: hendrikmuhs/ccache-action@v1.2.14 uses: hendrikmuhs/ccache-action@v1.2.14
env: env:
cache-name: ${{ runner.os }}-qt-cache-cmake-build cache-name: ${{ runner.os }}-qt-gcc-cache-cmake-build
with: with:
append-timestamp: false append-timestamp: false
key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }} key: ${{ env.cache-name }}-${{ hashFiles('**/CMakeLists.txt', 'cmake/**') }}

View File

@ -120,7 +120,7 @@ find_package(SDL3 3.1.2 CONFIG)
find_package(stb MODULE) find_package(stb MODULE)
find_package(toml11 4.2.0 CONFIG) find_package(toml11 4.2.0 CONFIG)
find_package(tsl-robin-map 1.3.0 CONFIG) find_package(tsl-robin-map 1.3.0 CONFIG)
find_package(VulkanHeaders 1.4.303 CONFIG) find_package(VulkanHeaders 1.4.305 CONFIG)
find_package(VulkanMemoryAllocator 3.1.0 CONFIG) find_package(VulkanMemoryAllocator 3.1.0 CONFIG)
find_package(xbyak 7.07 CONFIG) find_package(xbyak 7.07 CONFIG)
find_package(xxHash 0.8.2 MODULE) find_package(xxHash 0.8.2 MODULE)
@ -250,6 +250,8 @@ set(KERNEL_LIB src/core/libraries/kernel/sync/mutex.cpp
src/core/libraries/kernel/time.h src/core/libraries/kernel/time.h
src/core/libraries/kernel/orbis_error.h src/core/libraries/kernel/orbis_error.h
src/core/libraries/kernel/posix_error.h src/core/libraries/kernel/posix_error.h
src/core/libraries/kernel/aio.cpp
src/core/libraries/kernel/aio.h
) )
set(NETWORK_LIBS src/core/libraries/network/http.cpp set(NETWORK_LIBS src/core/libraries/network/http.cpp
@ -555,6 +557,16 @@ set(CORE src/core/aerolib/stubs.cpp
src/core/devices/logger.cpp src/core/devices/logger.cpp
src/core/devices/logger.h src/core/devices/logger.h
src/core/devices/nop_device.h src/core/devices/nop_device.h
src/core/devices/console_device.cpp
src/core/devices/console_device.h
src/core/devices/deci_tty6_device.cpp
src/core/devices/deci_tty6_device.h
src/core/devices/random_device.cpp
src/core/devices/random_device.h
src/core/devices/urandom_device.cpp
src/core/devices/urandom_device.h
src/core/devices/srandom_device.cpp
src/core/devices/srandom_device.h
src/core/file_format/pfs.h src/core/file_format/pfs.h
src/core/file_format/pkg.cpp src/core/file_format/pkg.cpp
src/core/file_format/pkg.h src/core/file_format/pkg.h

View File

@ -14,6 +14,7 @@ path = [
"documents/changelog.md", "documents/changelog.md",
"documents/Quickstart/2.png", "documents/Quickstart/2.png",
"documents/Screenshots/*", "documents/Screenshots/*",
"documents/Screenshots/Linux/*",
"externals/MoltenVK/MoltenVK_icd.json", "externals/MoltenVK/MoltenVK_icd.json",
"scripts/ps4_names.txt", "scripts/ps4_names.txt",
"src/images/about_icon.png", "src/images/about_icon.png",

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

View File

@ -3,59 +3,131 @@ SPDX-FileCopyrightText: 2024 shadPS4 Emulator Project
SPDX-License-Identifier: GPL-2.0-or-later SPDX-License-Identifier: GPL-2.0-or-later
--> -->
## Build shadPS4 for Linux ## Build shadPS4 for Linux
### Install the necessary tools to build shadPS4: First and foremost, Clang 18 is the **recommended compiler** as it is used for official builds and CI. If you build with GCC, you might encounter issues — please report any you find. Additionally, if you choose to use GCC, please build shadPS4 with Clang at least once before creating an `[APP BUG]` issue or submitting a pull request.
## Preparatory steps
### Installing dependencies
#### Debian & Ubuntu #### Debian & Ubuntu
``` ```
sudo apt install build-essential clang git cmake libasound2-dev libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev vulkan-validationlayers sudo apt install build-essential clang git cmake libasound2-dev libpulse-dev libopenal-dev libssl-dev zlib1g-dev libedit-dev libudev-dev libevdev-dev libsdl2-dev libjack-dev libsndio-dev qt6-base-dev qt6-tools-dev qt6-multimedia-dev libvulkan-dev vulkan-validationlayers
``` ```
#### Fedora #### Fedora
``` ```
sudo dnf install clang git cmake libatomic alsa-lib-devel pipewire-jack-audio-connection-kit-devel openal-devel openssl-devel libevdev-devel libudev-devel libXext-devel qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel vulkan-devel vulkan-validation-layers sudo dnf install clang git cmake libatomic alsa-lib-devel pipewire-jack-audio-connection-kit-devel openal-devel openssl-devel libevdev-devel libudev-devel libXext-devel qt6-qtbase-devel qt6-qtbase-private-devel qt6-qtmultimedia-devel qt6-qtsvg-devel qt6-qttools-devel vulkan-devel vulkan-validation-layers
``` ```
#### Arch Linux #### Arch Linux
``` ```
sudo pacman -S base-devel clang git cmake sndio jack2 openal qt6-base qt6-declarative qt6-multimedia sdl2 vulkan-validation-layers sudo pacman -S base-devel clang git cmake sndio jack2 openal qt6-base qt6-declarative qt6-multimedia sdl2 vulkan-validation-layers
``` ```
#### OpenSUSE **Note** : The `shadps4-git` AUR package is not maintained by any of the developers, and it uses the default compiler, which is often set to GCC. Use at your own discretion.#### OpenSUSE
``` ```
sudo zypper install clang git cmake libasound2 libpulse-devel libsndio7 libjack-devel openal-soft-devel libopenssl-devel zlib-devel libedit-devel systemd-devel libevdev-devel qt6-base-devel qt6-multimedia-devel qt6-svg-devel qt6-linguist-devel qt6-gui-private-devel vulkan-devel vulkan-validationlayers sudo zypper install clang git cmake libasound2 libpulse-devel libsndio7 libjack-devel openal-soft-devel libopenssl-devel zlib-devel libedit-devel systemd-devel libevdev-devel qt6-base-devel qt6-multimedia-devel qt6-svg-devel qt6-linguist-devel qt6-gui-private-devel vulkan-devel vulkan-validationlayers
``` ```
### Cloning and compiling:
Clone the repository recursively: #### Other Linux distributions
You can try one of two methods:
- Search the packages by name and install them with your package manager, or
- Install [distrobox](https://distrobox.it/), create a container using any of the distributions cited above as a base, for Arch Linux you'd do:
```
distrobox create --name archlinux --init --image archlinux:latest
```
and install the dependencies on that container as cited above.
This option is **highly recommended** for NixOS and distributions with immutable/atomic filesystems (example: Fedora Kinoite, SteamOS).
### Cloning
``` ```
git clone --recursive https://github.com/shadps4-emu/shadPS4.git git clone --recursive https://github.com/shadps4-emu/shadPS4.git
cd shadPS4 cd shadPS4
``` ```
Generate the build directory in the shadPS4 directory. To disable the QT GUI, remove the ```-DENABLE_QT_GUI=ON``` flag: ## Building
There are 3 options you can choose from. Option 1 is **highly recommended**.
#### Option 1: Terminal-only
1. Generate the build directory in the shadPS4 directory.
**Note**: Clang is the compiler used for official builds and CI. If you build with GCC, you might encounter issues—please report any you find. If you choose to use GCC, we recommend building with Clang at least once before submitting a pull request.
``` ```
cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ cmake -S . -B build/ -DENABLE_QT_GUI=ON -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++
``` ```
Enter the directory: To disable the Qt GUI, remove the `-DENABLE_QT_GUI=ON` flag. To change the build type (for debugging), add `-DCMAKE_BUILD_TYPE=Debug`.
2. Use CMake to build the project:
``` ```
cd build/ cmake --build ./build --parallel$(nproc)
``` ```
Use make to build the project: If your computer freezes during this step, this could be caused by excessive system resource usage. In that case, remove `--parallel$(nproc)`.
Now run the emulator. If Qt was enabled at configure time:
``` ```
cmake --build . --parallel$(nproc) ./build/shadps4
``` ```
Now run the emulator. If QT is enabled:
```
./shadps4
```
Otherwise, specify the path to your PKG's boot file: Otherwise, specify the path to your PKG's boot file:
``` ```
./shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin ./build/shadps4 /"PATH"/"TO"/"GAME"/"FOLDER"/eboot.bin
``` ```
You can also specify the Game ID as an argument for which game to boot, as long as the folder containing the games is specified in config.toml (example: Bloodborne (US) is CUSA00900).
#### Option 2: Configuring with cmake-gui
`cmake-gui` should be installed by default alongside `cmake`, if not search for the package in your package manager and install it.
Open `cmake-gui` and specify the source code and build directories. If you cloned the source code to your Home directory, it would be `/home/user/shadPS4` and `/home/user/shadPS4/build`.
Click on Configure, select "Unix Makefiles", select "Specify native compilers", click Next and choose `clang` and `clang++` as the C and CXX compilers. Usually they are located in `/bin/clang` and `/bin/clang++`. Click on Finish and let it configure the project.
Now every option should be displayed in red. Change anything you want, then click on Generate to make the changes permanent, then open a terminal window and do step 2 of Option 1.
#### Option 3: Visual Studio Code
This option is pretty convoluted and should only be used if you have VSCode as your default IDE, or just prefer building and debugging projects through it. This also assumes that you're using an Arch Linux environment, as the naming for some options might differ from other distros.
[Download Visual Studio Code for your platform](https://code.visualstudio.com/download), or use [Code - OSS](https://github.com/microsoft/vscode) if you'd like. Code - OSS is available on most Linux distributions' package repositories (on Arch Linux it is simply named `code`).
Once set up, go to Extensions and install "CMake Tools":
![image](https://raw.githubusercontent.com/shadps4-emu/shadPS4/refs/heads/main/documents/Screenshots/Linux/3.png)
You can also install other CMake and Clang related extensions if you'd like, but this one is what enables you to configure and build CMake projects directly within VSCode.
Go to Settings, filter by `@ext:ms-vscode.cmake-tools configure` and disable this option:
![image](https://raw.githubusercontent.com/shadps4-emu/shadPS4/refs/heads/main/documents/Screenshots/Linux/1.png)
If you wish to build with the Qt GUI, add `-DENABLE_QT_GUI=ON` to the configure arguments:
![image](https://raw.githubusercontent.com/shadps4-emu/shadPS4/refs/heads/main/documents/Screenshots/Linux/2.png)
On the CMake tab, change the options as you wish, but make sure that it looks similar to or exactly like this:
![image](https://raw.githubusercontent.com/shadps4-emu/shadPS4/refs/heads/main/documents/Screenshots/Linux/4.png)
When hovering over Project Status > Configure, there should be an icon titled "Configure". Click on it and let it configure the project, then do the same for Project Status > Build.
If you want to debug it, change the build type under Project Status > Configure to Debug (it should be the default) and compile it, then click on the icon in Project Status > Debug. If you simply want to launch the shadPS4 executable from within VSCode, click on the icon in Project Status > Launch.
Don't forget to change the launch target for both options to the shadPS4 executable inside shadPS4/build:
![image](https://raw.githubusercontent.com/shadps4-emu/shadPS4/refs/heads/main/documents/Screenshots/Linux/5.png)

@ -1 +1 @@
Subproject commit 9f0b616d9e2c39464d2a859b79dbc655c4a30e7e Subproject commit 2473ce6f0ab7d5d8a49aa91b2e37f3447a939f18

2
externals/sdl3 vendored

@ -1 +1 @@
Subproject commit 22422f7748d5128135995ed34c8f8012861c7332 Subproject commit a336b62d8b0b97b09214e053203e442e2b6e2be5

@ -1 +1 @@
Subproject commit 6a74a7d65cafa19e38ec116651436cce6efd5b2e Subproject commit a03d2f6d5753b365d704d58161825890baad0755

View File

@ -0,0 +1,27 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#ifdef __linux__
#include <pthread.h>
#endif
namespace Common {
#ifdef PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
class AdaptiveMutex {
public:
void lock() {
pthread_mutex_lock(&mutex);
}
void unlock() {
pthread_mutex_unlock(&mutex);
}
private:
pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
};
#endif // PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP
} // namespace Common

View File

@ -45,6 +45,9 @@ static std::string logFilter;
static std::string logType = "async"; static std::string logType = "async";
static std::string userName = "shadPS4"; static std::string userName = "shadPS4";
static std::string updateChannel; static std::string updateChannel;
static std::string chooseHomeTab;
static u16 deadZoneLeft = 2.0;
static u16 deadZoneRight = 2.0;
static std::string backButtonBehavior = "left"; static std::string backButtonBehavior = "left";
static bool useSpecialPad = false; static bool useSpecialPad = false;
static int specialPadClass = 1; static int specialPadClass = 1;
@ -61,9 +64,10 @@ static u32 vblankDivider = 1;
static bool vkValidation = false; static bool vkValidation = false;
static bool vkValidationSync = false; static bool vkValidationSync = false;
static bool vkValidationGpu = false; static bool vkValidationGpu = false;
static bool rdocEnable = false;
static bool vkMarkers = false;
static bool vkCrashDiagnostic = false; static bool vkCrashDiagnostic = false;
static bool vkHostMarkers = false;
static bool vkGuestMarkers = false;
static bool rdocEnable = false;
static s16 cursorState = HideCursorState::Idle; static s16 cursorState = HideCursorState::Idle;
static int cursorHideTimeout = 5; // 5 seconds (default) static int cursorHideTimeout = 5; // 5 seconds (default)
static bool separateupdatefolder = false; static bool separateupdatefolder = false;
@ -75,6 +79,7 @@ static std::string trophyKey;
static bool load_game_size = true; static bool load_game_size = true;
std::vector<std::filesystem::path> settings_install_dirs = {}; std::vector<std::filesystem::path> settings_install_dirs = {};
std::filesystem::path settings_addon_install_dir = {}; std::filesystem::path settings_addon_install_dir = {};
std::filesystem::path save_data_path = {};
u32 main_window_geometry_x = 400; u32 main_window_geometry_x = 400;
u32 main_window_geometry_y = 400; u32 main_window_geometry_y = 400;
u32 main_window_geometry_w = 1280; u32 main_window_geometry_w = 1280;
@ -107,6 +112,13 @@ bool GetLoadGameSizeEnabled() {
return load_game_size; return load_game_size;
} }
std::filesystem::path GetSaveDataPath() {
if (save_data_path.empty()) {
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir);
}
return save_data_path;
}
void setLoadGameSizeEnabled(bool enable) { void setLoadGameSizeEnabled(bool enable) {
load_game_size = enable; load_game_size = enable;
} }
@ -139,6 +151,14 @@ bool getEnableDiscordRPC() {
return enableDiscordRPC; return enableDiscordRPC;
} }
u16 leftDeadZone() {
return deadZoneLeft;
}
u16 rightDeadZone() {
return deadZoneRight;
}
s16 getCursorState() { s16 getCursorState() {
return cursorState; return cursorState;
} }
@ -175,6 +195,10 @@ std::string getUpdateChannel() {
return updateChannel; return updateChannel;
} }
std::string getChooseHomeTab() {
return chooseHomeTab;
}
std::string getBackButtonBehavior() { std::string getBackButtonBehavior() {
return backButtonBehavior; return backButtonBehavior;
} }
@ -227,10 +251,6 @@ bool isRdocEnabled() {
return rdocEnable; return rdocEnable;
} }
bool isMarkersEnabled() {
return vkMarkers;
}
u32 vblankDiv() { u32 vblankDiv() {
return vblankDivider; return vblankDivider;
} }
@ -247,14 +267,20 @@ bool vkValidationGpuEnabled() {
return vkValidationGpu; return vkValidationGpu;
} }
bool vkMarkersEnabled() {
return vkMarkers || vkCrashDiagnostic; // Crash diagnostic forces markers on
}
bool vkCrashDiagnosticEnabled() { bool vkCrashDiagnosticEnabled() {
return vkCrashDiagnostic; return vkCrashDiagnostic;
} }
bool vkHostMarkersEnabled() {
// Forced on when crash diagnostic enabled.
return vkHostMarkers || vkCrashDiagnostic;
}
bool vkGuestMarkersEnabled() {
// Forced on when crash diagnostic enabled.
return vkGuestMarkers || vkCrashDiagnostic;
}
bool getSeparateUpdateEnabled() { bool getSeparateUpdateEnabled() {
return separateupdatefolder; return separateupdatefolder;
} }
@ -378,6 +404,9 @@ void setUserName(const std::string& type) {
void setUpdateChannel(const std::string& type) { void setUpdateChannel(const std::string& type) {
updateChannel = type; updateChannel = type;
} }
void setChooseHomeTab(const std::string& type) {
chooseHomeTab = type;
}
void setBackButtonBehavior(const std::string& type) { void setBackButtonBehavior(const std::string& type) {
backButtonBehavior = type; backButtonBehavior = type;
@ -489,6 +518,10 @@ void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_insta
settings_install_dirs = settings_install_dirs_config; settings_install_dirs = settings_install_dirs_config;
} }
void setSaveDataPath(const std::filesystem::path& path) {
save_data_path = path;
}
u32 getMainWindowGeometryX() { u32 getMainWindowGeometryX() {
return main_window_geometry_x; return main_window_geometry_x;
} }
@ -612,11 +645,14 @@ void load(const std::filesystem::path& path) {
compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false); compatibilityData = toml::find_or<bool>(general, "compatibilityEnabled", false);
checkCompatibilityOnStartup = checkCompatibilityOnStartup =
toml::find_or<bool>(general, "checkCompatibilityOnStartup", false); toml::find_or<bool>(general, "checkCompatibilityOnStartup", false);
chooseHomeTab = toml::find_or<std::string>(general, "chooseHomeTab", "Release");
} }
if (data.contains("Input")) { if (data.contains("Input")) {
const toml::value& input = data.at("Input"); const toml::value& input = data.at("Input");
deadZoneLeft = toml::find_or<float>(input, "deadZoneLeft", 2.0);
deadZoneRight = toml::find_or<float>(input, "deadZoneRight", 2.0);
cursorState = toml::find_or<int>(input, "cursorState", HideCursorState::Idle); cursorState = toml::find_or<int>(input, "cursorState", HideCursorState::Idle);
cursorHideTimeout = toml::find_or<int>(input, "cursorHideTimeout", 5); cursorHideTimeout = toml::find_or<int>(input, "cursorHideTimeout", 5);
backButtonBehavior = toml::find_or<std::string>(input, "backButtonBehavior", "left"); backButtonBehavior = toml::find_or<std::string>(input, "backButtonBehavior", "left");
@ -644,9 +680,10 @@ void load(const std::filesystem::path& path) {
vkValidation = toml::find_or<bool>(vk, "validation", false); vkValidation = toml::find_or<bool>(vk, "validation", false);
vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false); vkValidationSync = toml::find_or<bool>(vk, "validation_sync", false);
vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", true); vkValidationGpu = toml::find_or<bool>(vk, "validation_gpu", true);
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
vkMarkers = toml::find_or<bool>(vk, "rdocMarkersEnable", false);
vkCrashDiagnostic = toml::find_or<bool>(vk, "crashDiagnostic", false); vkCrashDiagnostic = toml::find_or<bool>(vk, "crashDiagnostic", false);
vkHostMarkers = toml::find_or<bool>(vk, "hostMarkers", false);
vkGuestMarkers = toml::find_or<bool>(vk, "guestMarkers", false);
rdocEnable = toml::find_or<bool>(vk, "rdocEnable", false);
} }
if (data.contains("Debug")) { if (data.contains("Debug")) {
@ -674,6 +711,8 @@ void load(const std::filesystem::path& path) {
addGameInstallDir(std::filesystem::path{dir}); addGameInstallDir(std::filesystem::path{dir});
} }
save_data_path = toml::find_fs_path_or(gui, "saveDataPath", {});
settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {}); settings_addon_install_dir = toml::find_fs_path_or(gui, "addonInstallDir", {});
main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0); main_window_geometry_x = toml::find_or<int>(gui, "geometry_x", 0);
main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0); main_window_geometry_y = toml::find_or<int>(gui, "geometry_y", 0);
@ -730,11 +769,14 @@ void save(const std::filesystem::path& path) {
data["General"]["logType"] = logType; data["General"]["logType"] = logType;
data["General"]["userName"] = userName; data["General"]["userName"] = userName;
data["General"]["updateChannel"] = updateChannel; data["General"]["updateChannel"] = updateChannel;
data["General"]["chooseHomeTab"] = chooseHomeTab;
data["General"]["showSplash"] = isShowSplash; data["General"]["showSplash"] = isShowSplash;
data["General"]["autoUpdate"] = isAutoUpdate; data["General"]["autoUpdate"] = isAutoUpdate;
data["General"]["separateUpdateEnabled"] = separateupdatefolder; data["General"]["separateUpdateEnabled"] = separateupdatefolder;
data["General"]["compatibilityEnabled"] = compatibilityData; data["General"]["compatibilityEnabled"] = compatibilityData;
data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup; data["General"]["checkCompatibilityOnStartup"] = checkCompatibilityOnStartup;
data["Input"]["deadZoneLeft"] = deadZoneLeft;
data["Input"]["deadZoneRight"] = deadZoneRight;
data["Input"]["cursorState"] = cursorState; data["Input"]["cursorState"] = cursorState;
data["Input"]["cursorHideTimeout"] = cursorHideTimeout; data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
data["Input"]["backButtonBehavior"] = backButtonBehavior; data["Input"]["backButtonBehavior"] = backButtonBehavior;
@ -752,9 +794,10 @@ void save(const std::filesystem::path& path) {
data["Vulkan"]["validation"] = vkValidation; data["Vulkan"]["validation"] = vkValidation;
data["Vulkan"]["validation_sync"] = vkValidationSync; data["Vulkan"]["validation_sync"] = vkValidationSync;
data["Vulkan"]["validation_gpu"] = vkValidationGpu; data["Vulkan"]["validation_gpu"] = vkValidationGpu;
data["Vulkan"]["rdocEnable"] = rdocEnable;
data["Vulkan"]["rdocMarkersEnable"] = vkMarkers;
data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic; data["Vulkan"]["crashDiagnostic"] = vkCrashDiagnostic;
data["Vulkan"]["hostMarkers"] = vkHostMarkers;
data["Vulkan"]["guestMarkers"] = vkGuestMarkers;
data["Vulkan"]["rdocEnable"] = rdocEnable;
data["Debug"]["DebugDump"] = isDebugDump; data["Debug"]["DebugDump"] = isDebugDump;
data["Debug"]["CollectShader"] = isShaderDebug; data["Debug"]["CollectShader"] = isShaderDebug;
@ -765,6 +808,7 @@ void save(const std::filesystem::path& path) {
install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data}); install_dirs.emplace_back(std::string{fmt::UTF(dirString.u8string()).data});
} }
data["GUI"]["installDirs"] = install_dirs; data["GUI"]["installDirs"] = install_dirs;
data["GUI"]["saveDataPath"] = std::string{fmt::UTF(save_data_path.u8string()).data};
data["GUI"]["loadGameSizeEnabled"] = load_game_size; data["GUI"]["loadGameSizeEnabled"] = load_game_size;
data["GUI"]["addonInstallDir"] = data["GUI"]["addonInstallDir"] =
@ -837,6 +881,7 @@ void setDefaultValues() {
} else { } else {
updateChannel = "Nightly"; updateChannel = "Nightly";
} }
chooseHomeTab = "General";
cursorState = HideCursorState::Idle; cursorState = HideCursorState::Idle;
cursorHideTimeout = 5; cursorHideTimeout = 5;
backButtonBehavior = "left"; backButtonBehavior = "left";
@ -852,9 +897,10 @@ void setDefaultValues() {
vkValidation = false; vkValidation = false;
vkValidationSync = false; vkValidationSync = false;
vkValidationGpu = false; vkValidationGpu = false;
rdocEnable = false;
vkMarkers = false;
vkCrashDiagnostic = false; vkCrashDiagnostic = false;
vkHostMarkers = false;
vkGuestMarkers = false;
rdocEnable = false;
emulator_language = "en"; emulator_language = "en";
m_language = 1; m_language = 1;
gpuId = -1; gpuId = -1;
@ -863,4 +909,4 @@ void setDefaultValues() {
checkCompatibilityOnStartup = false; checkCompatibilityOnStartup = false;
} }
} // namespace Config } // namespace Config

View File

@ -18,6 +18,7 @@ void saveMainWindow(const std::filesystem::path& path);
std::string getTrophyKey(); std::string getTrophyKey();
void setTrophyKey(std::string key); void setTrophyKey(std::string key);
bool GetLoadGameSizeEnabled(); bool GetLoadGameSizeEnabled();
std::filesystem::path GetSaveDataPath();
void setLoadGameSizeEnabled(bool enable); void setLoadGameSizeEnabled(bool enable);
bool getIsFullscreen(); bool getIsFullscreen();
std::string getFullscreenMode(); std::string getFullscreenMode();
@ -34,7 +35,10 @@ std::string getLogFilter();
std::string getLogType(); std::string getLogType();
std::string getUserName(); std::string getUserName();
std::string getUpdateChannel(); std::string getUpdateChannel();
std::string getChooseHomeTab();
u16 leftDeadZone();
u16 rightDeadZone();
s16 getCursorState(); s16 getCursorState();
int getCursorHideTimeout(); int getCursorHideTimeout();
std::string getBackButtonBehavior(); std::string getBackButtonBehavior();
@ -78,8 +82,10 @@ void setLanguage(u32 language);
void setNeoMode(bool enable); void setNeoMode(bool enable);
void setUserName(const std::string& type); void setUserName(const std::string& type);
void setUpdateChannel(const std::string& type); void setUpdateChannel(const std::string& type);
void setChooseHomeTab(const std::string& type);
void setSeparateUpdateEnabled(bool use); void setSeparateUpdateEnabled(bool use);
void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config); void setGameInstallDirs(const std::vector<std::filesystem::path>& settings_install_dirs_config);
void setSaveDataPath(const std::filesystem::path& path);
void setCompatibilityEnabled(bool use); void setCompatibilityEnabled(bool use);
void setCheckCompatibilityOnStartup(bool use); void setCheckCompatibilityOnStartup(bool use);
@ -100,8 +106,9 @@ void setRdocEnabled(bool enable);
bool vkValidationEnabled(); bool vkValidationEnabled();
bool vkValidationSyncEnabled(); bool vkValidationSyncEnabled();
bool vkValidationGpuEnabled(); bool vkValidationGpuEnabled();
bool vkMarkersEnabled();
bool vkCrashDiagnosticEnabled(); bool vkCrashDiagnosticEnabled();
bool vkHostMarkersEnabled();
bool vkGuestMarkersEnabled();
// Gui // Gui
void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h); void setMainWindowGeometry(u32 x, u32 y, u32 w, u32 h);

View File

@ -37,6 +37,10 @@ public:
void Start(); void Start();
void End(); void End();
std::chrono::nanoseconds GetTotalWait() const {
return total_wait;
}
}; };
} // namespace Common } // namespace Common

View File

@ -67,28 +67,25 @@ struct AddressSpace::Impl {
static constexpr size_t ReductionOnFail = 1_GB; static constexpr size_t ReductionOnFail = 1_GB;
static constexpr size_t MaxReductions = 10; static constexpr size_t MaxReductions = 10;
size_t reduction = 0;
size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize; size_t virtual_size = SystemManagedSize + SystemReservedSize + UserSize;
for (u32 i = 0; i < MaxReductions; i++) { for (u32 i = 0; i < MaxReductions; i++) {
virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size - reduction, virtual_base = static_cast<u8*>(VirtualAlloc2(process, NULL, virtual_size,
MEM_RESERVE | MEM_RESERVE_PLACEHOLDER, MEM_RESERVE | MEM_RESERVE_PLACEHOLDER,
PAGE_NOACCESS, &param, 1)); PAGE_NOACCESS, &param, 1));
if (virtual_base) { if (virtual_base) {
break; break;
} }
reduction += ReductionOnFail; virtual_size -= ReductionOnFail;
} }
ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}", ASSERT_MSG(virtual_base, "Unable to reserve virtual address space: {}",
Common::GetLastErrorMsg()); Common::GetLastErrorMsg());
// Take the reduction off of the system managed area, and leave the others unchanged.
reduction = size_t(virtual_base - SYSTEM_MANAGED_MIN);
system_managed_base = virtual_base;
system_managed_size = SystemManagedSize - reduction;
system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN); system_reserved_base = reinterpret_cast<u8*>(SYSTEM_RESERVED_MIN);
system_reserved_size = SystemReservedSize; system_reserved_size = SystemReservedSize;
system_managed_base = virtual_base;
system_managed_size = system_reserved_base - virtual_base;
user_base = reinterpret_cast<u8*>(USER_MIN); user_base = reinterpret_cast<u8*>(USER_MIN);
user_size = UserSize; user_size = virtual_base + virtual_size - user_base;
LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}", LOG_INFO(Kernel_Vmm, "System managed virtual memory region: {} - {}",
fmt::ptr(system_managed_base), fmt::ptr(system_managed_base),
@ -101,10 +98,8 @@ struct AddressSpace::Impl {
// Initializer placeholder tracker // Initializer placeholder tracker
const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base); const uintptr_t system_managed_addr = reinterpret_cast<uintptr_t>(system_managed_base);
const uintptr_t system_reserved_addr = reinterpret_cast<uintptr_t>(system_reserved_base);
const uintptr_t user_addr = reinterpret_cast<uintptr_t>(user_base);
regions.emplace(system_managed_addr, regions.emplace(system_managed_addr,
MemoryRegion{system_managed_addr, virtual_size - reduction, false}); MemoryRegion{system_managed_addr, virtual_size, false});
// Allocate backing file that represents the total physical memory. // Allocate backing file that represents the total physical memory.
backing_handle = backing_handle =

View File

@ -17,6 +17,8 @@ using namespace DebugStateType;
DebugStateImpl& DebugState = *Common::Singleton<DebugStateImpl>::Instance(); DebugStateImpl& DebugState = *Common::Singleton<DebugStateImpl>::Instance();
bool DebugStateType::showing_debug_menu_bar = false;
static ThreadID ThisThreadID() { static ThreadID ThisThreadID() {
#ifdef _WIN32 #ifdef _WIN32
return GetCurrentThreadId(); return GetCurrentThreadId();

View File

@ -35,6 +35,8 @@ class ShaderList;
namespace DebugStateType { namespace DebugStateType {
extern bool showing_debug_menu_bar;
enum class QueueType { enum class QueueType {
dcb = 0, dcb = 0,
ccb = 1, ccb = 1,
@ -153,6 +155,9 @@ class DebugStateImpl {
std::vector<ShaderDump> shader_dump_list{}; std::vector<ShaderDump> shader_dump_list{};
public: public:
float Framerate = 1.0f / 60.0f;
float FrameDeltaTime;
void ShowDebugMessage(std::string message) { void ShowDebugMessage(std::string message) {
if (message.empty()) { if (message.empty()) {
return; return;
@ -160,6 +165,10 @@ public:
debug_message_popup.push(std::move(message)); debug_message_popup.push(std::move(message));
} }
bool& IsShowingDebugMenuBar() {
return showing_debug_menu_bar;
}
void AddCurrentThreadToGuestList(); void AddCurrentThreadToGuestList();
void RemoveCurrentThreadFromGuestList(); void RemoveCurrentThreadFromGuestList();

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "base_device.h" #include "base_device.h"

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once

View File

@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "console_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> ConsoleDevice::Create(u32 handle, const char*, int, u16) {
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new ConsoleDevice(handle)));
}
int ConsoleDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t ConsoleDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t ConsoleDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::read(void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int ConsoleDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 ConsoleDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int ConsoleDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int ConsoleDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 ConsoleDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class ConsoleDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit ConsoleDevice(u32 handle) : handle(handle) {}
~ConsoleDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -0,0 +1,74 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h"
#include "deci_tty6_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> DeciTty6Device::Create(u32 handle, const char*, int, u16) {
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new DeciTty6Device(handle)));
}
int DeciTty6Device::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t DeciTty6Device::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t DeciTty6Device::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::read(void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int DeciTty6Device::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 DeciTty6Device::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int DeciTty6Device::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int DeciTty6Device::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 DeciTty6Device::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class DeciTty6Device final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit DeciTty6Device(u32 handle) : handle(handle) {}
~DeciTty6Device() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/logging/log.h" #include "common/logging/log.h"
#include "core/libraries/kernel/file_system.h" #include "core/libraries/kernel/file_system.h"
@ -17,10 +17,12 @@ s64 Logger::write(const void* buf, size_t nbytes) {
} }
size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) { size_t Logger::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
size_t total_written = 0;
for (int i = 0; i < iovcnt; i++) { for (int i = 0; i < iovcnt; i++) {
log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len); log(static_cast<const char*>(iov[i].iov_base), iov[i].iov_len);
total_written += iov[i].iov_len;
} }
return iovcnt; return total_written;
} }
s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) { s64 Logger::pwrite(const void* buf, size_t nbytes, u64 offset) {

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once

View File

@ -1,5 +1,5 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#pragma once #pragma once
#include "base_device.h" #include "base_device.h"
@ -17,36 +17,47 @@ public:
int ioctl(u64 cmd, Common::VaCtx* args) override { int ioctl(u64 cmd, Common::VaCtx* args) override {
return 0; return 0;
} }
s64 write(const void* buf, size_t nbytes) override { s64 write(const void* buf, size_t nbytes) override {
return 0; return 0;
} }
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override { size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
return 0; return 0;
} }
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override { size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override {
return 0; return 0;
} }
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override { s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override {
return 0; return 0;
} }
s64 lseek(s64 offset, int whence) override { s64 lseek(s64 offset, int whence) override {
return 0; return 0;
} }
s64 read(void* buf, size_t nbytes) override { s64 read(void* buf, size_t nbytes) override {
return 0; return 0;
} }
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override { int fstat(Libraries::Kernel::OrbisKernelStat* sb) override {
return 0; return 0;
} }
s32 fsync() override { s32 fsync() override {
return 0; return 0;
} }
int ftruncate(s64 length) override { int ftruncate(s64 length) override {
return 0; return 0;
} }
int getdents(void* buf, u32 nbytes, s64* basep) override { int getdents(void* buf, u32 nbytes, s64* basep) override {
return 0; return 0;
} }
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override { s64 pwrite(const void* buf, size_t nbytes, u64 offset) override {
return 0; return 0;
} }

View File

@ -0,0 +1,78 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include "common/logging/log.h"
#include "random_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> RandomDevice::Create(u32 handle, const char*, int, u16) {
std::srand(std::time(nullptr));
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new RandomDevice(handle)));
}
int RandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t RandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t RandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::lseek(s64 offset, int whence) {
return 0;
}
s64 RandomDevice::read(void* buf, size_t nbytes) {
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++) {
rbuf[i] = std::rand() & 0xFF;
}
return nbytes;
}
int RandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 RandomDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int RandomDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int RandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 RandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class RandomDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit RandomDevice(u32 handle) : handle(handle) {}
~RandomDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include "common/logging/log.h"
#include "srandom_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> SRandomDevice::Create(u32 handle, const char*, int, u16) {
std::srand(std::time(nullptr));
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new SRandomDevice(handle)));
}
int SRandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t SRandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t SRandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::read(void* buf, size_t nbytes) {
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++) {
rbuf[i] = std::rand();
}
return nbytes;
}
int SRandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 SRandomDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return s32();
}
int SRandomDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int SRandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 SRandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class SRandomDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit SRandomDevice(u32 handle) : handle(handle) {}
~SRandomDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -0,0 +1,79 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstdlib>
#include "common/logging/log.h"
#include "urandom_device.h"
namespace Core::Devices {
std::shared_ptr<BaseDevice> URandomDevice::Create(u32 handle, const char*, int, u16) {
std::srand(std::time(nullptr));
return std::shared_ptr<BaseDevice>(
reinterpret_cast<Devices::BaseDevice*>(new URandomDevice(handle)));
}
int URandomDevice::ioctl(u64 cmd, Common::VaCtx* args) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::write(const void* buf, size_t nbytes) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t URandomDevice::writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
size_t URandomDevice::readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::lseek(s64 offset, int whence) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::read(void* buf, size_t nbytes) {
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++) {
rbuf[i] = std::rand() & 0xFF;
}
return nbytes;
}
int URandomDevice::fstat(Libraries::Kernel::OrbisKernelStat* sb) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s32 URandomDevice::fsync() {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int URandomDevice::ftruncate(s64 length) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
int URandomDevice::getdents(void* buf, u32 nbytes, s64* basep) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
s64 URandomDevice::pwrite(const void* buf, size_t nbytes, u64 offset) {
LOG_ERROR(Kernel_Pthread, "(STUBBED) called");
return 0;
}
} // namespace Core::Devices

View File

@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <memory>
#include "base_device.h"
namespace Core::Devices {
class URandomDevice final : BaseDevice {
u32 handle;
public:
static std::shared_ptr<BaseDevice> Create(u32 handle, const char*, int, u16);
explicit URandomDevice(u32 handle) : handle(handle) {}
~URandomDevice() override = default;
int ioctl(u64 cmd, Common::VaCtx* args) override;
s64 write(const void* buf, size_t nbytes) override;
size_t readv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
size_t writev(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt) override;
s64 preadv(const Libraries::Kernel::SceKernelIovec* iov, int iovcnt, u64 offset) override;
s64 lseek(s64 offset, int whence) override;
s64 read(void* buf, size_t nbytes) override;
int fstat(Libraries::Kernel::OrbisKernelStat* sb) override;
s32 fsync() override;
int ftruncate(s64 length) override;
int getdents(void* buf, u32 nbytes, s64* basep) override;
s64 pwrite(const void* buf, size_t nbytes, u64 offset) override;
};
} // namespace Core::Devices

View File

@ -28,7 +28,6 @@ static bool show_simple_fps = false;
static bool visibility_toggled = false; static bool visibility_toggled = false;
static float fps_scale = 1.0f; static float fps_scale = 1.0f;
static bool show_advanced_debug = false;
static int dump_frame_count = 1; static int dump_frame_count = 1;
static Widget::FrameGraph frame_graph; static Widget::FrameGraph frame_graph;
@ -94,6 +93,12 @@ void L::DrawMenuBar() {
} }
ImGui::EndMenu(); ImGui::EndMenu();
} }
SameLine(ImGui::GetWindowWidth() - 30.0f);
if (Button("X", ImVec2(25, 25))) {
DebugState.IsShowingDebugMenuBar() = false;
}
EndMainMenuBar(); EndMainMenuBar();
} }
@ -253,8 +258,8 @@ void L::DrawAdvanced() {
} }
void L::DrawSimple() { void L::DrawSimple() {
const auto io = GetIO(); const float frameRate = DebugState.Framerate;
Text("%.1f FPS (%.2f ms)", io.Framerate, 1000.0f / io.Framerate); Text("%d FPS (%.1f ms)", static_cast<int>(std::round(frameRate)), 1000.0f / frameRate);
} }
static void LoadSettings(const char* line) { static void LoadSettings(const char* line) {
@ -265,7 +270,7 @@ static void LoadSettings(const char* line) {
return; return;
} }
if (sscanf(line, "show_advanced_debug=%d", &i) == 1) { if (sscanf(line, "show_advanced_debug=%d", &i) == 1) {
show_advanced_debug = i != 0; DebugState.IsShowingDebugMenuBar() = i != 0;
return; return;
} }
if (sscanf(line, "show_frame_graph=%d", &i) == 1) { if (sscanf(line, "show_frame_graph=%d", &i) == 1) {
@ -310,7 +315,7 @@ void L::SetupSettings() {
handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) { handler.WriteAllFn = [](ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf) {
buf->appendf("[%s][Data]\n", handler->TypeName); buf->appendf("[%s][Data]\n", handler->TypeName);
buf->appendf("fps_scale=%f\n", fps_scale); buf->appendf("fps_scale=%f\n", fps_scale);
buf->appendf("show_advanced_debug=%d\n", show_advanced_debug); buf->appendf("show_advanced_debug=%d\n", DebugState.IsShowingDebugMenuBar());
buf->appendf("show_frame_graph=%d\n", frame_graph.is_open); buf->appendf("show_frame_graph=%d\n", frame_graph.is_open);
buf->appendf("dump_frame_count=%d\n", dump_frame_count); buf->appendf("dump_frame_count=%d\n", dump_frame_count);
buf->append("\n"); buf->append("\n");
@ -336,12 +341,12 @@ void L::Draw() {
if (!DebugState.IsGuestThreadsPaused()) { if (!DebugState.IsGuestThreadsPaused()) {
const auto fn = DebugState.flip_frame_count.load(); const auto fn = DebugState.flip_frame_count.load();
frame_graph.AddFrame(fn, io.DeltaTime); frame_graph.AddFrame(fn, DebugState.FrameDeltaTime);
} }
if (IsKeyPressed(ImGuiKey_F10, false)) { if (IsKeyPressed(ImGuiKey_F10, false)) {
if (io.KeyCtrl) { if (io.KeyCtrl) {
show_advanced_debug = !show_advanced_debug; DebugState.IsShowingDebugMenuBar() ^= true;
} else { } else {
show_simple_fps = !show_simple_fps; show_simple_fps = !show_simple_fps;
} }
@ -376,7 +381,7 @@ void L::Draw() {
End(); End();
} }
if (show_advanced_debug) { if (DebugState.IsShowingDebugMenuBar()) {
PushFont(io.Fonts->Fonts[IMGUI_FONT_MONO]); PushFont(io.Fonts->Fonts[IMGUI_FONT_MONO]);
PushID("DevtoolsLayer"); PushID("DevtoolsLayer");
DrawAdvanced(); DrawAdvanced();

View File

@ -83,15 +83,13 @@ void FrameGraph::Draw() {
auto isSystemPaused = DebugState.IsGuestThreadsPaused(); auto isSystemPaused = DebugState.IsGuestThreadsPaused();
static float deltaTime;
static float frameRate;
if (!isSystemPaused) { if (!isSystemPaused) {
deltaTime = io.DeltaTime * 1000.0f; deltaTime = DebugState.FrameDeltaTime * 1000.0f;
frameRate = 1000.0f / deltaTime; frameRate = 1000.0f / deltaTime;
} }
Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate); Text("Frame time: %.3f ms (%.1f FPS)", deltaTime, frameRate);
Text("Presenter time: %.3f ms (%.1f FPS)", io.DeltaTime * 1000.0f, 1.0f / io.DeltaTime);
Text("Flip frame: %d Gnm submit frame: %d", DebugState.flip_frame_count.load(), Text("Flip frame: %d Gnm submit frame: %d", DebugState.flip_frame_count.load(),
DebugState.gnm_frame_count.load()); DebugState.gnm_frame_count.load());

View File

@ -16,6 +16,9 @@ class FrameGraph {
std::array<FrameInfo, FRAME_BUFFER_SIZE> frame_list{}; std::array<FrameInfo, FRAME_BUFFER_SIZE> frame_list{};
float deltaTime{};
float frameRate{};
void DrawFrameGraph(); void DrawFrameGraph();
public: public:

View File

@ -24,16 +24,33 @@ using namespace ImGui;
namespace Core::Devtools::Widget { namespace Core::Devtools::Widget {
ShaderList::Selection::Selection(int index) : index(index) { ShaderList::Selection::Selection(int index)
isa_editor.SetPalette(TextEditor::GetDarkPalette()); : index(index), isa_editor(std::make_unique<TextEditor>()),
isa_editor.SetReadOnly(true); glsl_editor(std::make_unique<TextEditor>()) {
glsl_editor.SetPalette(TextEditor::GetDarkPalette()); isa_editor->SetPalette(TextEditor::GetDarkPalette());
glsl_editor.SetLanguageDefinition(TextEditor::LanguageDefinition::GLSL()); isa_editor->SetReadOnly(true);
glsl_editor->SetPalette(TextEditor::GetDarkPalette());
glsl_editor->SetLanguageDefinition(TextEditor::LanguageDefinition::GLSL());
presenter->GetWindow().RequestKeyboard(); presenter->GetWindow().RequestKeyboard();
} }
ShaderList::Selection::~Selection() { ShaderList::Selection::~Selection() {
presenter->GetWindow().ReleaseKeyboard(); if (index >= 0) {
presenter->GetWindow().ReleaseKeyboard();
}
}
ShaderList::Selection::Selection(Selection&& other) noexcept
: index{other.index}, isa_editor{std::move(other.isa_editor)},
glsl_editor{std::move(other.glsl_editor)}, open{other.open}, showing_bin{other.showing_bin},
patch_path{std::move(other.patch_path)}, patch_bin_path{std::move(other.patch_bin_path)} {
other.index = -1;
}
ShaderList::Selection& ShaderList::Selection::operator=(Selection other) {
using std::swap;
swap(*this, other);
return *this;
} }
void ShaderList::Selection::ReloadShader(DebugStateType::ShaderDump& value) { void ShaderList::Selection::ReloadShader(DebugStateType::ShaderDump& value) {
@ -72,13 +89,13 @@ bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) {
value.is_patched = !value.patch_spv.empty(); value.is_patched = !value.patch_spv.empty();
if (!value.is_patched) { // No patch if (!value.is_patched) { // No patch
isa_editor.SetText(value.cache_isa_disasm); isa_editor->SetText(value.cache_isa_disasm);
glsl_editor.SetText(value.cache_spv_disasm); glsl_editor->SetText(value.cache_spv_disasm);
} else { } else {
isa_editor.SetText(value.cache_patch_disasm); isa_editor->SetText(value.cache_patch_disasm);
isa_editor.SetLanguageDefinition(TextEditor::LanguageDefinition::SPIRV()); isa_editor->SetLanguageDefinition(TextEditor::LanguageDefinition::SPIRV());
glsl_editor.SetText(value.patch_source); glsl_editor->SetText(value.patch_source);
glsl_editor.SetReadOnly(false); glsl_editor->SetReadOnly(false);
} }
} }
@ -97,18 +114,18 @@ bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) {
if (value.patch_source.empty()) { if (value.patch_source.empty()) {
value.patch_source = value.cache_spv_disasm; value.patch_source = value.cache_spv_disasm;
} }
isa_editor.SetText(value.cache_patch_disasm); isa_editor->SetText(value.cache_patch_disasm);
isa_editor.SetLanguageDefinition(TextEditor::LanguageDefinition::SPIRV()); isa_editor->SetLanguageDefinition(TextEditor::LanguageDefinition::SPIRV());
glsl_editor.SetText(value.patch_source); glsl_editor->SetText(value.patch_source);
glsl_editor.SetReadOnly(false); glsl_editor->SetReadOnly(false);
if (!value.patch_spv.empty()) { if (!value.patch_spv.empty()) {
ReloadShader(value); ReloadShader(value);
} }
} else { } else {
isa_editor.SetText(value.cache_isa_disasm); isa_editor->SetText(value.cache_isa_disasm);
isa_editor.SetLanguageDefinition(TextEditor::LanguageDefinition()); isa_editor->SetLanguageDefinition(TextEditor::LanguageDefinition());
glsl_editor.SetText(value.cache_spv_disasm); glsl_editor->SetText(value.cache_spv_disasm);
glsl_editor.SetReadOnly(true); glsl_editor->SetReadOnly(true);
ReloadShader(value); ReloadShader(value);
} }
} }
@ -154,7 +171,7 @@ bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) {
compile = true; compile = true;
} }
if (save) { if (save) {
value.patch_source = glsl_editor.GetText(); value.patch_source = glsl_editor->GetText();
std::ofstream file{patch_path, std::ios::binary | std::ios::trunc}; std::ofstream file{patch_path, std::ios::binary | std::ios::trunc};
file << value.patch_source; file << value.patch_source;
std::string msg = "Patch saved to "; std::string msg = "Patch saved to ";
@ -192,7 +209,7 @@ bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) {
DebugState.ShowDebugMessage("Decompilation failed (Compile was ok):\n" + DebugState.ShowDebugMessage("Decompilation failed (Compile was ok):\n" +
res); res);
} else { } else {
isa_editor.SetText(value.cache_patch_disasm); isa_editor->SetText(value.cache_patch_disasm);
ReloadShader(value); ReloadShader(value);
} }
} }
@ -201,9 +218,9 @@ bool ShaderList::Selection::DrawShader(DebugStateType::ShaderDump& value) {
} }
if (showing_bin) { if (showing_bin) {
isa_editor.Render(value.is_patched ? "SPIRV" : "ISA", GetContentRegionAvail()); isa_editor->Render(value.is_patched ? "SPIRV" : "ISA", GetContentRegionAvail());
} else { } else {
glsl_editor.Render("GLSL", GetContentRegionAvail()); glsl_editor->Render("GLSL", GetContentRegionAvail());
} }
End(); End();

View File

@ -14,14 +14,17 @@ class ShaderList {
struct Selection { struct Selection {
explicit Selection(int index); explicit Selection(int index);
~Selection(); ~Selection();
Selection(const Selection& other) = delete;
Selection(Selection&& other) noexcept;
Selection& operator=(Selection other);
void ReloadShader(DebugStateType::ShaderDump& value); void ReloadShader(DebugStateType::ShaderDump& value);
bool DrawShader(DebugStateType::ShaderDump& value); bool DrawShader(DebugStateType::ShaderDump& value);
int index; int index{-1};
TextEditor isa_editor{}; std::unique_ptr<TextEditor> isa_editor{};
TextEditor glsl_editor{}; std::unique_ptr<TextEditor> glsl_editor{};
bool open = true; bool open = true;
bool showing_bin = false; bool showing_bin = false;

View File

@ -233,7 +233,7 @@ void HandleTable::CreateStdHandles() {
std::shared_ptr<Devices::BaseDevice>{reinterpret_cast<Devices::BaseDevice*>(device)}; std::shared_ptr<Devices::BaseDevice>{reinterpret_cast<Devices::BaseDevice*>(device)};
}; };
// order matters // order matters
setup("/dev/stdin", new Devices::NopDevice(0)); // stdin setup("/dev/stdin", new Devices::Logger("stdin", false)); // stdin
setup("/dev/stdout", new Devices::Logger("stdout", false)); // stdout setup("/dev/stdout", new Devices::Logger("stdout", false)); // stdout
setup("/dev/stderr", new Devices::Logger("stderr", true)); // stderr setup("/dev/stderr", new Devices::Logger("stderr", true)); // stderr
} }

View File

@ -0,0 +1,339 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <thread>
#include "aio.h"
#include "common/assert.h"
#include "common/debug.h"
#include "common/logging/log.h"
#include "core/libraries/kernel/equeue.h"
#include "core/libraries/kernel/orbis_error.h"
#include "core/libraries/libs.h"
#include "file_system.h"
namespace Libraries::Kernel {
#define MAX_QUEUE 512
static s32* id_state;
static s32 id_index;
s32 sceKernelAioInitializeImpl(void* p, s32 size) {
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioDeleteRequest(OrbisKernelAioSubmitId id, s32* ret) {
if (ret == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
id_state[id] = ORBIS_KERNEL_AIO_STATE_ABORTED;
*ret = 0;
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioDeleteRequests(OrbisKernelAioSubmitId id[], s32 num, s32 ret[]) {
if (ret == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
for (s32 i = 0; i < num; i++) {
id_state[id[i]] = ORBIS_KERNEL_AIO_STATE_ABORTED;
ret[i] = 0;
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioPollRequest(OrbisKernelAioSubmitId id, s32* state) {
if (state == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
*state = id_state[id];
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioPollRequests(OrbisKernelAioSubmitId id[], s32 num, s32 state[]) {
if (state == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
for (s32 i = 0; i < num; i++) {
state[i] = id_state[id[i]];
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioCancelRequest(OrbisKernelAioSubmitId id, s32* state) {
if (state == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (id) {
id_state[id] = ORBIS_KERNEL_AIO_STATE_ABORTED;
*state = ORBIS_KERNEL_AIO_STATE_ABORTED;
} else {
*state = ORBIS_KERNEL_AIO_STATE_PROCESSING;
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioCancelRequests(OrbisKernelAioSubmitId id[], s32 num, s32 state[]) {
if (state == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
for (s32 i = 0; i < num; i++) {
if (id[i]) {
id_state[id[i]] = ORBIS_KERNEL_AIO_STATE_ABORTED;
state[i] = ORBIS_KERNEL_AIO_STATE_ABORTED;
} else {
state[i] = ORBIS_KERNEL_AIO_STATE_PROCESSING;
}
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioWaitRequest(OrbisKernelAioSubmitId id, s32* state, u32* usec) {
if (state == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
u32 timer = 0;
s32 timeout = 0;
while (id_state[id] == ORBIS_KERNEL_AIO_STATE_PROCESSING) {
sceKernelUsleep(10);
timer += 10;
if (*usec) {
if (timer > *usec) {
timeout = 1;
break;
}
}
}
*state = id_state[id];
if (timeout)
return ORBIS_KERNEL_ERROR_ETIMEDOUT;
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioWaitRequests(OrbisKernelAioSubmitId id[], s32 num, s32 state[],
u32 mode, u32* usec) {
if (state == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
u32 timer = 0;
s32 timeout = 0;
s32 completion = 0;
for (s32 i = 0; i < num; i++) {
if (!completion && !timeout) {
while (id_state[id[i]] == ORBIS_KERNEL_AIO_STATE_PROCESSING) {
sceKernelUsleep(10);
timer += 10;
if (*usec) {
if (timer > *usec) {
timeout = 1;
break;
}
}
}
}
if (mode == 0x02) {
if (id_state[id[i]] == ORBIS_KERNEL_AIO_STATE_COMPLETED)
completion = 1;
}
state[i] = id_state[id[i]];
}
if (timeout)
return ORBIS_KERNEL_ERROR_ETIMEDOUT;
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioSubmitReadCommands(OrbisKernelAioRWRequest req[], s32 size, s32 prio,
OrbisKernelAioSubmitId* id) {
if (req == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (id == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_PROCESSING;
for (s32 i = 0; i < size; i++) {
s64 ret = sceKernelPread(req[i].fd, req[i].buf, req[i].nbyte, req[i].offset);
if (ret < 0) {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_ABORTED;
req[i].result->returnValue = ret;
} else {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_COMPLETED;
req[i].result->returnValue = ret;
}
}
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_COMPLETED;
*id = id_index;
id_index = (id_index + 1) % MAX_QUEUE;
if (!id_index)
id_index++;
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioSubmitReadCommandsMultiple(OrbisKernelAioRWRequest req[], s32 size,
s32 prio, OrbisKernelAioSubmitId id[]) {
if (req == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (id == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
for (s32 i = 0; i < size; i++) {
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_PROCESSING;
s64 ret = sceKernelPread(req[i].fd, req[i].buf, req[i].nbyte, req[i].offset);
if (ret < 0) {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_ABORTED;
req[i].result->returnValue = ret;
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_ABORTED;
} else {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_COMPLETED;
req[i].result->returnValue = ret;
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_COMPLETED;
}
id[i] = id_index;
id_index = (id_index + 1) % MAX_QUEUE;
if (!id_index)
id_index++;
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioSubmitWriteCommands(OrbisKernelAioRWRequest req[], s32 size, s32 prio,
OrbisKernelAioSubmitId* id) {
if (req == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (id == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
for (s32 i = 0; i < size; i++) {
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_PROCESSING;
s64 ret = sceKernelPwrite(req[i].fd, req[i].buf, req[i].nbyte, req[i].offset);
if (ret < 0) {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_ABORTED;
req[i].result->returnValue = ret;
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_ABORTED;
} else {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_COMPLETED;
req[i].result->returnValue = ret;
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_COMPLETED;
}
}
*id = id_index;
id_index = (id_index + 1) % MAX_QUEUE;
// skip id_index equals 0 , because sceKernelAioCancelRequest will submit id
// equal to 0
if (!id_index)
id_index++;
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioSubmitWriteCommandsMultiple(OrbisKernelAioRWRequest req[], s32 size,
s32 prio, OrbisKernelAioSubmitId id[]) {
if (req == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
if (id == nullptr) {
return ORBIS_KERNEL_ERROR_EFAULT;
}
for (s32 i = 0; i < size; i++) {
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_PROCESSING;
s64 ret = sceKernelPwrite(req[i].fd, req[i].buf, req[i].nbyte, req[i].offset);
if (ret < 0) {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_ABORTED;
req[i].result->returnValue = ret;
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_ABORTED;
} else {
req[i].result->state = ORBIS_KERNEL_AIO_STATE_COMPLETED;
req[i].result->returnValue = ret;
id_state[id_index] = ORBIS_KERNEL_AIO_STATE_COMPLETED;
}
id[i] = id_index;
id_index = (id_index + 1) % MAX_QUEUE;
if (!id_index)
id_index++;
}
return 0;
}
s32 PS4_SYSV_ABI sceKernelAioSetParam() {
LOG_ERROR(Kernel, "(STUBBED) called");
return ORBIS_OK;
}
s32 PS4_SYSV_ABI sceKernelAioInitializeParam() {
LOG_ERROR(Kernel, "(STUBBED) called");
return ORBIS_OK;
}
void RegisterAio(Core::Loader::SymbolsResolver* sym) {
id_index = 1;
id_state = (int*)malloc(sizeof(int) * MAX_QUEUE);
memset(id_state, 0, sizeof(sizeof(int) * MAX_QUEUE));
LIB_FUNCTION("fR521KIGgb8", "libkernel", 1, "libkernel", 1, 1, sceKernelAioCancelRequest);
LIB_FUNCTION("3Lca1XBrQdY", "libkernel", 1, "libkernel", 1, 1, sceKernelAioCancelRequests);
LIB_FUNCTION("5TgME6AYty4", "libkernel", 1, "libkernel", 1, 1, sceKernelAioDeleteRequest);
LIB_FUNCTION("Ft3EtsZzAoY", "libkernel", 1, "libkernel", 1, 1, sceKernelAioDeleteRequests);
LIB_FUNCTION("vYU8P9Td2Zo", "libkernel", 1, "libkernel", 1, 1, sceKernelAioInitializeImpl);
LIB_FUNCTION("nu4a0-arQis", "libkernel", 1, "libkernel", 1, 1, sceKernelAioInitializeParam);
LIB_FUNCTION("2pOuoWoCxdk", "libkernel", 1, "libkernel", 1, 1, sceKernelAioPollRequest);
LIB_FUNCTION("o7O4z3jwKzo", "libkernel", 1, "libkernel", 1, 1, sceKernelAioPollRequests);
LIB_FUNCTION("9WK-vhNXimw", "libkernel", 1, "libkernel", 1, 1, sceKernelAioSetParam);
LIB_FUNCTION("HgX7+AORI58", "libkernel", 1, "libkernel", 1, 1, sceKernelAioSubmitReadCommands);
LIB_FUNCTION("lXT0m3P-vs4", "libkernel", 1, "libkernel", 1, 1,
sceKernelAioSubmitReadCommandsMultiple);
LIB_FUNCTION("XQ8C8y+de+E", "libkernel", 1, "libkernel", 1, 1, sceKernelAioSubmitWriteCommands);
LIB_FUNCTION("xT3Cpz0yh6Y", "libkernel", 1, "libkernel", 1, 1,
sceKernelAioSubmitWriteCommandsMultiple);
LIB_FUNCTION("KOF-oJbQVvc", "libkernel", 1, "libkernel", 1, 1, sceKernelAioWaitRequest);
LIB_FUNCTION("lgK+oIWkJyA", "libkernel", 1, "libkernel", 1, 1, sceKernelAioWaitRequests);
}
} // namespace Libraries::Kernel

View File

@ -0,0 +1,43 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <condition_variable>
#include <mutex>
#include <string>
#include <vector>
#include <boost/asio/steady_timer.hpp>
#include "common/types.h"
namespace Core::Loader {
class SymbolsResolver;
}
namespace Libraries::Kernel {
enum AioState {
ORBIS_KERNEL_AIO_STATE_SUBMITTED = 1,
ORBIS_KERNEL_AIO_STATE_PROCESSING = 2,
ORBIS_KERNEL_AIO_STATE_COMPLETED = 3,
ORBIS_KERNEL_AIO_STATE_ABORTED = 4
};
struct OrbisKernelAioResult {
s64 returnValue;
u32 state;
};
typedef s32 OrbisKernelAioSubmitId;
struct OrbisKernelAioRWRequest {
s64 offset;
s64 nbyte;
void* buf;
OrbisKernelAioResult* result;
s32 fd;
};
void RegisterAio(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Kernel

View File

@ -8,8 +8,13 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/singleton.h" #include "common/singleton.h"
#include "core/devices/console_device.h"
#include "core/devices/deci_tty6_device.h"
#include "core/devices/logger.h" #include "core/devices/logger.h"
#include "core/devices/nop_device.h" #include "core/devices/nop_device.h"
#include "core/devices/random_device.h"
#include "core/devices/srandom_device.h"
#include "core/devices/urandom_device.h"
#include "core/file_sys/fs.h" #include "core/file_sys/fs.h"
#include "core/libraries/kernel/file_system.h" #include "core/libraries/kernel/file_system.h"
#include "core/libraries/kernel/orbis_error.h" #include "core/libraries/kernel/orbis_error.h"
@ -41,6 +46,12 @@ static std::map<std::string, FactoryDevice> available_device = {
{"/dev/deci_stderr", GET_DEVICE_FD(2)}, {"/dev/deci_stderr", GET_DEVICE_FD(2)},
{"/dev/null", GET_DEVICE_FD(0)}, // fd0 (stdin) is a nop device {"/dev/null", GET_DEVICE_FD(0)}, // fd0 (stdin) is a nop device
{"/dev/urandom", &D::URandomDevice::Create },
{"/dev/random", &D::RandomDevice::Create },
{"/dev/srandom", &D::SRandomDevice::Create },
{"/dev/console", &D::ConsoleDevice::Create },
{"/dev/deci_tty6",&D::DeciTty6Device::Create }
// clang-format on // clang-format on
}; };
@ -67,17 +78,6 @@ int PS4_SYSV_ABI sceKernelOpen(const char* raw_path, int flags, u16 mode) {
bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0; bool directory = (flags & ORBIS_KERNEL_O_DIRECTORY) != 0;
std::string_view path{raw_path}; std::string_view path{raw_path};
if (path == "/dev/console") {
return 2000;
}
if (path == "/dev/deci_tty6") {
return 2001;
}
if (path == "/dev/urandom") {
return 2003;
}
u32 handle = h->CreateHandle(); u32 handle = h->CreateHandle();
auto* file = h->GetFile(handle); auto* file = h->GetFile(handle);
@ -167,9 +167,6 @@ int PS4_SYSV_ABI sceKernelClose(int d) {
if (d < 3) { // d probably hold an error code if (d < 3) { // d probably hold an error code
return ORBIS_KERNEL_ERROR_EPERM; return ORBIS_KERNEL_ERROR_EPERM;
} }
if (d == 2003) { // dev/urandom case
return ORBIS_OK;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(d); auto* file = h->GetFile(d);
if (file == nullptr) { if (file == nullptr) {
@ -273,13 +270,6 @@ size_t PS4_SYSV_ABI _readv(int d, const SceKernelIovec* iov, int iovcnt) {
} }
size_t PS4_SYSV_ABI _writev(int fd, const SceKernelIovec* iov, int iovcn) { size_t PS4_SYSV_ABI _writev(int fd, const SceKernelIovec* iov, int iovcn) {
if (fd == 1) {
size_t total_written = 0;
for (int i = 0; i < iovcn; i++) {
total_written += ::fwrite(iov[i].iov_base, 1, iov[i].iov_len, stdout);
}
return total_written;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(fd); auto* file = h->GetFile(fd);
if (file == nullptr) { if (file == nullptr) {
@ -337,13 +327,6 @@ s64 PS4_SYSV_ABI posix_lseek(int d, s64 offset, int whence) {
} }
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) { s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes) {
if (d == 2003) // dev urandom case
{
auto rbuf = static_cast<char*>(buf);
for (size_t i = 0; i < nbytes; i++)
rbuf[i] = std::rand() & 0xFF;
return nbytes;
}
auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance(); auto* h = Common::Singleton<Core::FileSys::HandleTable>::Instance();
auto* file = h->GetFile(d); auto* file = h->GetFile(d);
if (file == nullptr) { if (file == nullptr) {
@ -757,7 +740,6 @@ s32 PS4_SYSV_ABI sceKernelRename(const char* from, const char* to) {
} }
void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) { void RegisterFileSystem(Core::Loader::SymbolsResolver* sym) {
std::srand(std::time(nullptr));
LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen); LIB_FUNCTION("1G3lF1Gg1k8", "libkernel", 1, "libkernel", 1, 1, sceKernelOpen);
LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open); LIB_FUNCTION("wuCroIGjt2g", "libScePosix", 1, "libkernel", 1, 1, posix_open);
LIB_FUNCTION("wuCroIGjt2g", "libkernel", 1, "libkernel", 1, 1, open); LIB_FUNCTION("wuCroIGjt2g", "libkernel", 1, "libkernel", 1, 1, open);

View File

@ -67,7 +67,8 @@ constexpr int ORBIS_KERNEL_O_DIRECTORY = 0x00020000;
s64 PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes); s64 PS4_SYSV_ABI sceKernelWrite(int d, const void* buf, size_t nbytes);
s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes); s64 PS4_SYSV_ABI sceKernelRead(int d, void* buf, size_t nbytes);
s64 PS4_SYSV_ABI sceKernelPread(int d, void* buf, size_t nbytes, s64 offset);
s64 PS4_SYSV_ABI sceKernelPwrite(int d, void* buf, size_t nbytes, s64 offset);
void RegisterFileSystem(Core::Loader::SymbolsResolver* sym); void RegisterFileSystem(Core::Loader::SymbolsResolver* sym);
} // namespace Libraries::Kernel } // namespace Libraries::Kernel

View File

@ -28,6 +28,7 @@
#include <Rpc.h> #include <Rpc.h>
#endif #endif
#include <common/singleton.h> #include <common/singleton.h>
#include "aio.h"
namespace Libraries::Kernel { namespace Libraries::Kernel {
@ -59,7 +60,7 @@ static void KernelServiceThread(std::stop_token stoken) {
} }
io_context.run(); io_context.run();
io_context.reset(); io_context.restart();
asio_requests = 0; asio_requests = 0;
} }
@ -218,6 +219,7 @@ void RegisterKernel(Core::Loader::SymbolsResolver* sym) {
Libraries::Kernel::RegisterEventQueue(sym); Libraries::Kernel::RegisterEventQueue(sym);
Libraries::Kernel::RegisterProcess(sym); Libraries::Kernel::RegisterProcess(sym);
Libraries::Kernel::RegisterException(sym); Libraries::Kernel::RegisterException(sym);
Libraries::Kernel::RegisterAio(sym);
LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard); LIB_OBJ("f7uOxY9mM1U", "libkernel", 1, "libkernel", 1, 1, &g_stack_chk_guard);
LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl); LIB_FUNCTION("PfccT7qURYE", "libkernel", 1, "libkernel", 1, 1, kernel_ioctl);

View File

@ -153,6 +153,11 @@ int PS4_SYSV_ABI sceKernelDebugRaiseException() {
return 0; return 0;
} }
int PS4_SYSV_ABI sceKernelDebugRaiseExceptionOnReleaseMode() {
UNREACHABLE();
return 0;
}
void RegisterException(Core::Loader::SymbolsResolver* sym) { void RegisterException(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("il03nluKfMk", "libkernel_unity", 1, "libkernel", 1, 1, sceKernelRaiseException); LIB_FUNCTION("il03nluKfMk", "libkernel_unity", 1, "libkernel", 1, 1, sceKernelRaiseException);
LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", 1, 1, LIB_FUNCTION("WkwEd3N7w0Y", "libkernel_unity", 1, "libkernel", 1, 1,
@ -160,6 +165,8 @@ void RegisterException(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("Qhv5ARAoOEc", "libkernel_unity", 1, "libkernel", 1, 1, LIB_FUNCTION("Qhv5ARAoOEc", "libkernel_unity", 1, "libkernel", 1, 1,
sceKernelRemoveExceptionHandler) sceKernelRemoveExceptionHandler)
LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException); LIB_FUNCTION("OMDRKKAZ8I4", "libkernel", 1, "libkernel", 1, 1, sceKernelDebugRaiseException);
LIB_FUNCTION("zE-wXIZjLoM", "libkernel", 1, "libkernel", 1, 1,
sceKernelDebugRaiseExceptionOnReleaseMode);
} }
} // namespace Libraries::Kernel } // namespace Libraries::Kernel

View File

@ -82,6 +82,7 @@ int PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2,
int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, OrbisTimesec* st, int PS4_SYSV_ABI sceKernelConvertUtcToLocaltime(time_t time, time_t* local_time, OrbisTimesec* st,
u64* dst_sec); u64* dst_sec);
int PS4_SYSV_ABI sceKernelUsleep(u32 microseconds);
void RegisterTime(Core::Loader::SymbolsResolver* sym); void RegisterTime(Core::Loader::SymbolsResolver* sym);

View File

@ -93,7 +93,7 @@ int PS4_SYSV_ABI sceNetCtlUnregisterCallbackV6() {
} }
int PS4_SYSV_ABI sceNetCtlCheckCallback() { int PS4_SYSV_ABI sceNetCtlCheckCallback() {
netctl.CheckCallback(); LOG_DEBUG(Lib_NetCtl, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }
@ -373,7 +373,7 @@ int PS4_SYSV_ABI Func_D8DCB6973537A3DC() {
} }
int PS4_SYSV_ABI sceNetCtlCheckCallbackForNpToolkit() { int PS4_SYSV_ABI sceNetCtlCheckCallbackForNpToolkit() {
netctl.CheckNpToolkitCallback(); LOG_DEBUG(Lib_NetCtl, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -5,6 +5,7 @@
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/libs.h" #include "core/libraries/libs.h"
#include "core/libraries/np_manager/np_manager.h" #include "core/libraries/np_manager/np_manager.h"
#include "core/libraries/np_manager/np_manager_error.h"
#include "core/tls.h" #include "core/tls.h"
namespace Libraries::NpManager { namespace Libraries::NpManager {
@ -935,14 +936,22 @@ int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetAccountId() { int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id) {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_DEBUG(Lib_NpManager, "called");
return ORBIS_OK; if (online_id == nullptr || account_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*account_id = 0;
return ORBIS_NP_ERROR_SIGNED_OUT;
} }
int PS4_SYSV_ABI sceNpGetAccountIdA() { int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account_id) {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
return ORBIS_OK; if (account_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*account_id = 0;
return ORBIS_NP_ERROR_SIGNED_OUT;
} }
int PS4_SYSV_ABI sceNpGetAccountLanguage() { int PS4_SYSV_ABI sceNpGetAccountLanguage() {
@ -972,6 +981,9 @@ int PS4_SYSV_ABI sceNpGetGamePresenceStatusA() {
int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) { int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id) {
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id); LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
if (np_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
return ORBIS_NP_ERROR_SIGNED_OUT; return ORBIS_NP_ERROR_SIGNED_OUT;
} }
@ -980,8 +992,11 @@ int PS4_SYSV_ABI sceNpGetNpReachabilityState() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetOnlineId(s32 user_id, OrbisNpOnlineId* online_id) { int PS4_SYSV_ABI sceNpGetOnlineId(OrbisUserServiceUserId user_id, OrbisNpOnlineId* online_id) {
LOG_DEBUG(Lib_NpManager, "user_id {}", user_id); LOG_DEBUG(Lib_NpManager, "user_id {}", user_id);
if (online_id == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
return ORBIS_NP_ERROR_SIGNED_OUT; return ORBIS_NP_ERROR_SIGNED_OUT;
} }
@ -995,7 +1010,10 @@ int PS4_SYSV_ABI sceNpGetParentalControlInfoA() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpGetState(s32 userId, OrbisNpState* state) { int PS4_SYSV_ABI sceNpGetState(OrbisUserServiceUserId user_id, OrbisNpState* state) {
if (state == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*state = OrbisNpState::SignedOut; *state = OrbisNpState::SignedOut;
LOG_DEBUG(Lib_NpManager, "Signed out"); LOG_DEBUG(Lib_NpManager, "Signed out");
return ORBIS_OK; return ORBIS_OK;
@ -1011,8 +1029,12 @@ int PS4_SYSV_ABI sceNpGetUserIdByOnlineId() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNpHasSignedUp() { int PS4_SYSV_ABI sceNpHasSignedUp(OrbisUserServiceUserId user_id, bool* has_signed_up) {
LOG_ERROR(Lib_NpManager, "(STUBBED) called"); LOG_DEBUG(Lib_NpManager, "called");
if (has_signed_up == nullptr) {
return ORBIS_NP_ERROR_INVALID_ARGUMENT;
}
*has_signed_up = false;
return ORBIS_OK; return ORBIS_OK;
} }
@ -2509,7 +2531,7 @@ struct NpStateCallbackForNpToolkit {
NpStateCallbackForNpToolkit NpStateCbForNp; NpStateCallbackForNpToolkit NpStateCbForNp;
int PS4_SYSV_ABI sceNpCheckCallbackForLib() { int PS4_SYSV_ABI sceNpCheckCallbackForLib() {
Core::ExecuteGuest(NpStateCbForNp.func, 1, OrbisNpState::SignedOut, NpStateCbForNp.userdata); LOG_DEBUG(Lib_NpManager, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -11,8 +11,6 @@ class SymbolsResolver;
namespace Libraries::NpManager { namespace Libraries::NpManager {
constexpr int ORBIS_NP_ERROR_SIGNED_OUT = 0x80550006;
enum class OrbisNpState : u32 { Unknown = 0, SignedOut, SignedIn }; enum class OrbisNpState : u32 { Unknown = 0, SignedOut, SignedIn };
using OrbisNpStateCallbackForNpToolkit = PS4_SYSV_ABI void (*)(s32 userId, OrbisNpState state, using OrbisNpStateCallbackForNpToolkit = PS4_SYSV_ABI void (*)(s32 userId, OrbisNpState state,
@ -220,22 +218,22 @@ int PS4_SYSV_ABI sceNpGetAccountCountry();
int PS4_SYSV_ABI sceNpGetAccountCountryA(); int PS4_SYSV_ABI sceNpGetAccountCountryA();
int PS4_SYSV_ABI sceNpGetAccountDateOfBirth(); int PS4_SYSV_ABI sceNpGetAccountDateOfBirth();
int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA(); int PS4_SYSV_ABI sceNpGetAccountDateOfBirthA();
int PS4_SYSV_ABI sceNpGetAccountId(); int PS4_SYSV_ABI sceNpGetAccountId(OrbisNpOnlineId* online_id, u64* account_id);
int PS4_SYSV_ABI sceNpGetAccountIdA(); int PS4_SYSV_ABI sceNpGetAccountIdA(OrbisUserServiceUserId user_id, u64* account_id);
int PS4_SYSV_ABI sceNpGetAccountLanguage(); int PS4_SYSV_ABI sceNpGetAccountLanguage();
int PS4_SYSV_ABI sceNpGetAccountLanguage2(); int PS4_SYSV_ABI sceNpGetAccountLanguage2();
int PS4_SYSV_ABI sceNpGetAccountLanguageA(); int PS4_SYSV_ABI sceNpGetAccountLanguageA();
int PS4_SYSV_ABI sceNpGetGamePresenceStatus(); int PS4_SYSV_ABI sceNpGetGamePresenceStatus();
int PS4_SYSV_ABI sceNpGetGamePresenceStatusA(); int PS4_SYSV_ABI sceNpGetGamePresenceStatusA();
int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId userId, OrbisNpId* npId); int PS4_SYSV_ABI sceNpGetNpId(OrbisUserServiceUserId user_id, OrbisNpId* np_id);
int PS4_SYSV_ABI sceNpGetNpReachabilityState(); int PS4_SYSV_ABI sceNpGetNpReachabilityState();
int PS4_SYSV_ABI sceNpGetOnlineId(s32 userId, OrbisNpOnlineId* onlineId); int PS4_SYSV_ABI sceNpGetOnlineId(OrbisUserServiceUserId user_id, OrbisNpOnlineId* online_id);
int PS4_SYSV_ABI sceNpGetParentalControlInfo(); int PS4_SYSV_ABI sceNpGetParentalControlInfo();
int PS4_SYSV_ABI sceNpGetParentalControlInfoA(); int PS4_SYSV_ABI sceNpGetParentalControlInfoA();
int PS4_SYSV_ABI sceNpGetState(s32 userId, OrbisNpState* state); int PS4_SYSV_ABI sceNpGetState(OrbisUserServiceUserId user_id, OrbisNpState* state);
int PS4_SYSV_ABI sceNpGetUserIdByAccountId(); int PS4_SYSV_ABI sceNpGetUserIdByAccountId();
int PS4_SYSV_ABI sceNpGetUserIdByOnlineId(); int PS4_SYSV_ABI sceNpGetUserIdByOnlineId();
int PS4_SYSV_ABI sceNpHasSignedUp(); int PS4_SYSV_ABI sceNpHasSignedUp(OrbisUserServiceUserId user_id, bool* has_signed_up);
int PS4_SYSV_ABI sceNpIdMapperAbortRequest(); int PS4_SYSV_ABI sceNpIdMapperAbortRequest();
int PS4_SYSV_ABI sceNpIdMapperAccountIdToNpId(); int PS4_SYSV_ABI sceNpIdMapperAccountIdToNpId();
int PS4_SYSV_ABI sceNpIdMapperAccountIdToOnlineId(); int PS4_SYSV_ABI sceNpIdMapperAccountIdToOnlineId();

View File

@ -0,0 +1,9 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "core/libraries/error_codes.h"
constexpr int ORBIS_NP_ERROR_INVALID_ARGUMENT = 0x80550003;
constexpr int ORBIS_NP_ERROR_SIGNED_OUT = 0x80550006;

View File

@ -11,6 +11,8 @@
namespace Libraries::Pad { namespace Libraries::Pad {
using Input::GameController;
int PS4_SYSV_ABI scePadClose(s32 handle) { int PS4_SYSV_ABI scePadClose(s32 handle) {
LOG_ERROR(Lib_Pad, "(STUBBED) called"); LOG_ERROR(Lib_Pad, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
@ -93,8 +95,8 @@ int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerIn
pInfo->touchPadInfo.pixelDensity = 1; pInfo->touchPadInfo.pixelDensity = 1;
pInfo->touchPadInfo.resolution.x = 1920; pInfo->touchPadInfo.resolution.x = 1920;
pInfo->touchPadInfo.resolution.y = 950; pInfo->touchPadInfo.resolution.y = 950;
pInfo->stickInfo.deadZoneLeft = 2; pInfo->stickInfo.deadZoneLeft = Config::leftDeadZone();
pInfo->stickInfo.deadZoneRight = 2; pInfo->stickInfo.deadZoneRight = Config::rightDeadZone();
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD; pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD;
pInfo->connectedCount = 1; pInfo->connectedCount = 1;
pInfo->connected = false; pInfo->connected = false;
@ -104,8 +106,8 @@ int PS4_SYSV_ABI scePadGetControllerInformation(s32 handle, OrbisPadControllerIn
pInfo->touchPadInfo.pixelDensity = 1; pInfo->touchPadInfo.pixelDensity = 1;
pInfo->touchPadInfo.resolution.x = 1920; pInfo->touchPadInfo.resolution.x = 1920;
pInfo->touchPadInfo.resolution.y = 950; pInfo->touchPadInfo.resolution.y = 950;
pInfo->stickInfo.deadZoneLeft = 2; pInfo->stickInfo.deadZoneLeft = Config::leftDeadZone();
pInfo->stickInfo.deadZoneRight = 2; pInfo->stickInfo.deadZoneRight = Config::rightDeadZone();
pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD; pInfo->connectionType = ORBIS_PAD_PORT_TYPE_STANDARD;
pInfo->connectedCount = 1; pInfo->connectedCount = 1;
pInfo->connected = true; pInfo->connected = true;
@ -290,7 +292,8 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
int connected_count = 0; int connected_count = 0;
bool connected = false; bool connected = false;
Input::State states[64]; Input::State states[64];
auto* controller = Common::Singleton<Input::GameController>::Instance(); auto* controller = Common::Singleton<GameController>::Instance();
const auto* engine = controller->GetEngine();
int ret_num = controller->ReadStates(states, num, &connected, &connected_count); int ret_num = controller->ReadStates(states, num, &connected, &connected_count);
if (!connected) { if (!connected) {
@ -311,9 +314,14 @@ int PS4_SYSV_ABI scePadRead(s32 handle, OrbisPadData* pData, s32 num) {
pData[i].angularVelocity.x = states[i].angularVelocity.x; pData[i].angularVelocity.x = states[i].angularVelocity.x;
pData[i].angularVelocity.y = states[i].angularVelocity.y; pData[i].angularVelocity.y = states[i].angularVelocity.y;
pData[i].angularVelocity.z = states[i].angularVelocity.z; pData[i].angularVelocity.z = states[i].angularVelocity.z;
Input::GameController::CalculateOrientation(pData[i].acceleration, pData[i].angularVelocity, if (engine) {
1.0f / controller->accel_poll_rate, const auto accel_poll_rate = engine->GetAccelPollRate();
pData[i].orientation); if (accel_poll_rate != 0.0f) {
GameController::CalculateOrientation(pData[i].acceleration,
pData[i].angularVelocity,
1.0f / accel_poll_rate, pData[i].orientation);
}
}
pData[i].touchData.touchNum = pData[i].touchData.touchNum =
(states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0); (states[i].touchpad[0].state ? 1 : 0) + (states[i].touchpad[1].state ? 1 : 0);
pData[i].touchData.touch[0].x = states[i].touchpad[0].x; pData[i].touchData.touch[0].x = states[i].touchpad[0].x;
@ -356,7 +364,8 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
if (handle == ORBIS_PAD_ERROR_DEVICE_NO_HANDLE) { if (handle == ORBIS_PAD_ERROR_DEVICE_NO_HANDLE) {
return ORBIS_PAD_ERROR_INVALID_HANDLE; return ORBIS_PAD_ERROR_INVALID_HANDLE;
} }
auto* controller = Common::Singleton<Input::GameController>::Instance(); auto* controller = Common::Singleton<GameController>::Instance();
const auto* engine = controller->GetEngine();
int connectedCount = 0; int connectedCount = 0;
bool isConnected = false; bool isConnected = false;
Input::State state; Input::State state;
@ -374,9 +383,13 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
pData->angularVelocity.x = state.angularVelocity.x; pData->angularVelocity.x = state.angularVelocity.x;
pData->angularVelocity.y = state.angularVelocity.y; pData->angularVelocity.y = state.angularVelocity.y;
pData->angularVelocity.z = state.angularVelocity.z; pData->angularVelocity.z = state.angularVelocity.z;
Input::GameController::CalculateOrientation(pData->acceleration, pData->angularVelocity, if (engine) {
1.0f / controller->accel_poll_rate, const auto accel_poll_rate = engine->GetAccelPollRate();
pData->orientation); if (accel_poll_rate != 0.0f) {
GameController::CalculateOrientation(pData->acceleration, pData->angularVelocity,
1.0f / accel_poll_rate, pData->orientation);
}
}
pData->touchData.touchNum = pData->touchData.touchNum =
(state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0); (state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0);
pData->touchData.touch[0].x = state.touchpad[0].x; pData->touchData.touch[0].x = state.touchpad[0].x;
@ -468,7 +481,7 @@ int PS4_SYSV_ABI scePadSetLightBar(s32 handle, const OrbisPadLightBarParam* pPar
return ORBIS_PAD_ERROR_INVALID_LIGHTBAR_SETTING; return ORBIS_PAD_ERROR_INVALID_LIGHTBAR_SETTING;
} }
auto* controller = Common::Singleton<Input::GameController>::Instance(); auto* controller = Common::Singleton<GameController>::Instance();
controller->SetLightBarRGB(pParam->r, pParam->g, pParam->b); controller->SetLightBarRGB(pParam->r, pParam->g, pParam->b);
return ORBIS_OK; return ORBIS_OK;
} }
@ -536,7 +549,7 @@ int PS4_SYSV_ABI scePadSetVibration(s32 handle, const OrbisPadVibrationParam* pP
if (pParam != nullptr) { if (pParam != nullptr) {
LOG_DEBUG(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle, LOG_DEBUG(Lib_Pad, "scePadSetVibration called handle = {} data = {} , {}", handle,
pParam->smallMotor, pParam->largeMotor); pParam->smallMotor, pParam->largeMotor);
auto* controller = Common::Singleton<Input::GameController>::Instance(); auto* controller = Common::Singleton<GameController>::Instance();
controller->SetVibration(pParam->smallMotor, pParam->largeMotor); controller->SetVibration(pParam->smallMotor, pParam->largeMotor);
return ORBIS_OK; return ORBIS_OK;
} }

View File

@ -47,15 +47,13 @@ namespace Libraries::SaveData {
std::filesystem::path SaveInstance::MakeTitleSavePath(OrbisUserServiceUserId user_id, std::filesystem::path SaveInstance::MakeTitleSavePath(OrbisUserServiceUserId user_id,
std::string_view game_serial) { std::string_view game_serial) {
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / return Config::GetSaveDataPath() / std::to_string(user_id) / game_serial;
game_serial;
} }
std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_id, std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_id,
std::string_view game_serial, std::string_view game_serial,
std::string_view dir_name) { std::string_view dir_name) {
return Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / std::to_string(user_id) / return Config::GetSaveDataPath() / std::to_string(user_id) / game_serial / dir_name;
game_serial / dir_name;
} }
uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) { uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) {

View File

@ -1,8 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <imgui.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/config.h" #include "common/config.h"
#include "common/debug.h" #include "common/debug.h"
@ -11,6 +9,7 @@
#include "core/libraries/kernel/time.h" #include "core/libraries/kernel/time.h"
#include "core/libraries/videoout/driver.h" #include "core/libraries/videoout/driver.h"
#include "core/libraries/videoout/videoout_error.h" #include "core/libraries/videoout/videoout_error.h"
#include "imgui/renderer/imgui_core.h"
#include "video_core/renderer_vulkan/vk_presenter.h" #include "video_core/renderer_vulkan/vk_presenter.h"
extern std::unique_ptr<Vulkan::Presenter> presenter; extern std::unique_ptr<Vulkan::Presenter> presenter;
@ -207,6 +206,13 @@ void VideoOutDriver::DrawBlankFrame() {
presenter->Present(empty_frame); presenter->Present(empty_frame);
} }
void VideoOutDriver::DrawLastFrame() {
const auto frame = presenter->PrepareLastFrame();
if (frame != nullptr) {
presenter->Present(frame, true);
}
}
bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg,
bool is_eop /*= false*/) { bool is_eop /*= false*/) {
{ {
@ -278,17 +284,26 @@ void VideoOutDriver::PresentThread(std::stop_token token) {
return {}; return {};
}; };
auto delay = std::chrono::microseconds{0};
while (!token.stop_requested()) { while (!token.stop_requested()) {
timer.Start(); timer.Start();
if (DebugState.IsGuestThreadsPaused()) {
DrawLastFrame();
timer.End();
continue;
}
// Check if it's time to take a request. // Check if it's time to take a request.
auto& vblank_status = main_port.vblank_status; auto& vblank_status = main_port.vblank_status;
if (vblank_status.count % (main_port.flip_rate + 1) == 0) { if (vblank_status.count % (main_port.flip_rate + 1) == 0) {
const auto request = receive_request(); const auto request = receive_request();
if (!request) { if (!request) {
if (!main_port.is_open || DebugState.IsGuestThreadsPaused()) { if (timer.GetTotalWait().count() < 0) { // Dont draw too fast
DrawBlankFrame(); if (!main_port.is_open) {
DrawBlankFrame();
} else if (ImGui::Core::MustKeepDrawing()) {
DrawLastFrame();
}
} }
} else { } else {
Flip(request); Flip(request);

View File

@ -102,7 +102,8 @@ private:
}; };
void Flip(const Request& req); void Flip(const Request& req);
void DrawBlankFrame(); // Used when there is no flip request to keep ImGui up to date void DrawBlankFrame(); // Video port out not open
void DrawLastFrame(); // Used when there is no flip request
void SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false); void SubmitFlipInternal(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop = false);
void PresentThread(std::stop_token token); void PresentThread(std::stop_token token);

View File

@ -52,7 +52,7 @@ Linker::Linker() : memory{Memory::Instance()} {}
Linker::~Linker() = default; Linker::~Linker() = default;
void Linker::Execute() { void Linker::Execute(const std::vector<std::string> args) {
if (Config::debugDump()) { if (Config::debugDump()) {
DebugDump(); DebugDump();
} }
@ -101,7 +101,7 @@ void Linker::Execute() {
memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2); memory->SetupMemoryRegions(fmem_size, use_extended_mem1, use_extended_mem2);
main_thread.Run([this, module](std::stop_token) { main_thread.Run([this, module, args](std::stop_token) {
Common::SetCurrentThreadName("GAME_MainThread"); Common::SetCurrentThreadName("GAME_MainThread");
LoadSharedLibraries(); LoadSharedLibraries();
@ -109,6 +109,12 @@ void Linker::Execute() {
EntryParams params{}; EntryParams params{};
params.argc = 1; params.argc = 1;
params.argv[0] = "eboot.bin"; params.argv[0] = "eboot.bin";
if (!args.empty()) {
params.argc = args.size() + 1;
for (int i = 0; i < args.size() && i < 32; i++) {
params.argv[i + 1] = args[i].c_str();
}
}
params.entry_addr = module->GetEntryAddress(); params.entry_addr = module->GetEntryAddress();
RunMainEntry(&params); RunMainEntry(&params);
}); });

View File

@ -49,7 +49,7 @@ class Linker;
struct EntryParams { struct EntryParams {
int argc; int argc;
u32 padding; u32 padding;
const char* argv[3]; const char* argv[33];
VAddr entry_addr; VAddr entry_addr;
}; };
@ -143,7 +143,7 @@ public:
void Relocate(Module* module); void Relocate(Module* module);
bool Resolve(const std::string& name, Loader::SymbolType type, Module* module, bool Resolve(const std::string& name, Loader::SymbolType type, Module* module,
Loader::SymbolRecord* return_info); Loader::SymbolRecord* return_info);
void Execute(); void Execute(const std::vector<std::string> args = {});
void DebugDump(); void DebugDump();
private: private:

View File

@ -532,8 +532,8 @@ int MemoryManager::VirtualQuery(VAddr addr, int flags,
info->is_flexible.Assign(vma.type == VMAType::Flexible); info->is_flexible.Assign(vma.type == VMAType::Flexible);
info->is_direct.Assign(vma.type == VMAType::Direct); info->is_direct.Assign(vma.type == VMAType::Direct);
info->is_stack.Assign(vma.type == VMAType::Stack); info->is_stack.Assign(vma.type == VMAType::Stack);
info->is_pooled.Assign(vma.type == VMAType::PoolReserved); info->is_pooled.Assign(vma.type == VMAType::PoolReserved || vma.type == VMAType::Pooled);
info->is_committed.Assign(vma.type == VMAType::Pooled); info->is_committed.Assign(vma.IsMapped());
vma.name.copy(info->name.data(), std::min(info->name.size(), vma.name.size())); vma.name.copy(info->name.data(), std::min(info->name.size(), vma.name.size()));
if (vma.type == VMAType::Direct) { if (vma.type == VMAType::Direct) {
const auto dmem_it = FindDmemArea(vma.phys_base); const auto dmem_it = FindDmemArea(vma.phys_base);

View File

@ -66,9 +66,10 @@ Emulator::Emulator() {
LOG_INFO(Config, "Vulkan vkValidation: {}", Config::vkValidationEnabled()); LOG_INFO(Config, "Vulkan vkValidation: {}", Config::vkValidationEnabled());
LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled()); LOG_INFO(Config, "Vulkan vkValidationSync: {}", Config::vkValidationSyncEnabled());
LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled()); LOG_INFO(Config, "Vulkan vkValidationGpu: {}", Config::vkValidationGpuEnabled());
LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled());
LOG_INFO(Config, "Vulkan rdocMarkersEnable: {}", Config::vkMarkersEnabled());
LOG_INFO(Config, "Vulkan crashDiagnostics: {}", Config::vkCrashDiagnosticEnabled()); LOG_INFO(Config, "Vulkan crashDiagnostics: {}", Config::vkCrashDiagnosticEnabled());
LOG_INFO(Config, "Vulkan hostMarkers: {}", Config::vkHostMarkersEnabled());
LOG_INFO(Config, "Vulkan guestMarkers: {}", Config::vkGuestMarkersEnabled());
LOG_INFO(Config, "Vulkan rdocEnable: {}", Config::isRdocEnabled());
// Create stdin/stdout/stderr // Create stdin/stdout/stderr
Common::Singleton<FileSys::HandleTable>::Instance()->CreateStdHandles(); Common::Singleton<FileSys::HandleTable>::Instance()->CreateStdHandles();
@ -98,7 +99,7 @@ Emulator::~Emulator() {
Config::saveMainWindow(config_dir / "config.toml"); Config::saveMainWindow(config_dir / "config.toml");
} }
void Emulator::Run(const std::filesystem::path& file) { void Emulator::Run(const std::filesystem::path& file, const std::vector<std::string> args) {
// Applications expect to be run from /app0 so mount the file's parent path as app0. // Applications expect to be run from /app0 so mount the file's parent path as app0.
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
const auto game_folder = file.parent_path(); const auto game_folder = file.parent_path();
@ -151,6 +152,15 @@ void Emulator::Run(const std::filesystem::path& file) {
if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) { if (const auto raw_attributes = param_sfo->GetInteger("ATTRIBUTE")) {
psf_attributes.raw = *raw_attributes; psf_attributes.raw = *raw_attributes;
} }
if (!args.empty()) {
int argc = std::min<int>(args.size(), 32);
for (int i = 0; i < argc; i++) {
LOG_INFO(Loader, "Game argument {}: {}", i, args[i]);
}
if (args.size() > 32) {
LOG_ERROR(Loader, "Too many game arguments, only passing the first 32");
}
}
} }
const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png"); const auto pic1_path = mnt->GetHostPath("/app0/sce_sys/pic1.png");
@ -238,7 +248,7 @@ void Emulator::Run(const std::filesystem::path& file) {
} }
#endif #endif
linker->Execute(); linker->Execute(args);
window->InitTimers(); window->InitTimers();
while (window->IsOpen()) { while (window->IsOpen()) {

View File

@ -25,7 +25,7 @@ public:
Emulator(); Emulator();
~Emulator(); ~Emulator();
void Run(const std::filesystem::path& file); void Run(const std::filesystem::path& file, const std::vector<std::string> args = {});
void UpdatePlayTime(const std::string& serial); void UpdatePlayTime(const std::string& serial);
private: private:

View File

@ -30,6 +30,12 @@ extern void assert_fail_debug_msg(const char* msg);
#define IM_VEC4_CLASS_EXTRA \ #define IM_VEC4_CLASS_EXTRA \
constexpr ImVec4(float _v) : x(_v), y(_v), z(_v), w(_v) {} constexpr ImVec4(float _v) : x(_v), y(_v), z(_v), w(_v) {}
namespace ImGui {
struct Texture;
}
#define ImTextureID ImTextureID
using ImTextureID = ::ImGui::Texture*;
#ifdef IMGUI_USE_WCHAR32 #ifdef IMGUI_USE_WCHAR32
#error "This project uses 16 bits wchar standard like Orbis" #error "This project uses 16 bits wchar standard like Orbis"
#endif #endif

View File

@ -6,6 +6,7 @@
#include "common/config.h" #include "common/config.h"
#include "common/path_util.h" #include "common/path_util.h"
#include "core/debug_state.h"
#include "core/devtools/layer.h" #include "core/devtools/layer.h"
#include "imgui/imgui_layer.h" #include "imgui/imgui_layer.h"
#include "imgui_core.h" #include "imgui_core.h"
@ -167,7 +168,7 @@ bool ProcessEvent(SDL_Event* event) {
} }
} }
void NewFrame() { ImGuiID NewFrame(bool is_reusing_frame) {
{ {
std::scoped_lock lock{change_layers_mutex}; std::scoped_lock lock{change_layers_mutex};
while (!change_layers.empty()) { while (!change_layers.empty()) {
@ -182,24 +183,32 @@ void NewFrame() {
} }
} }
Sdl::NewFrame(); Sdl::NewFrame(is_reusing_frame);
ImGui::NewFrame(); ImGui::NewFrame();
DockSpaceOverViewport(0, GetMainViewport(), ImGuiDockNodeFlags_PassthruCentralNode); ImGuiWindowFlags flags =
ImGuiDockNodeFlags_PassthruCentralNode | ImGuiDockNodeFlags_AutoHideTabBar;
if (!DebugState.IsShowingDebugMenuBar()) {
flags |= ImGuiDockNodeFlags_NoTabBar;
}
ImGuiID dockId = DockSpaceOverViewport(0, GetMainViewport(), flags);
for (auto* layer : layers) { for (auto* layer : layers) {
layer->Draw(); layer->Draw();
} }
return dockId;
} }
void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) { void Render(const vk::CommandBuffer& cmdbuf, const vk::ImageView& image_view,
const vk::Extent2D& extent) {
ImGui::Render(); ImGui::Render();
ImDrawData* draw_data = GetDrawData(); ImDrawData* draw_data = GetDrawData();
if (draw_data->CmdListsCount == 0) { if (draw_data->CmdListsCount == 0) {
return; return;
} }
if (Config::vkMarkersEnabled()) { if (Config::vkHostMarkersEnabled()) {
cmdbuf.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{ cmdbuf.beginDebugUtilsLabelEXT(vk::DebugUtilsLabelEXT{
.pLabelName = "ImGui Render", .pLabelName = "ImGui Render",
}); });
@ -207,16 +216,16 @@ void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
vk::RenderingAttachmentInfo color_attachments[1]{ vk::RenderingAttachmentInfo color_attachments[1]{
{ {
.imageView = frame->image_view, .imageView = image_view,
.imageLayout = vk::ImageLayout::eColorAttachmentOptimal, .imageLayout = vk::ImageLayout::eColorAttachmentOptimal,
.loadOp = vk::AttachmentLoadOp::eLoad, .loadOp = vk::AttachmentLoadOp::eClear,
.storeOp = vk::AttachmentStoreOp::eStore, .storeOp = vk::AttachmentStoreOp::eStore,
}, },
}; };
vk::RenderingInfo render_info{}; vk::RenderingInfo render_info{};
render_info.renderArea = vk::Rect2D{ render_info.renderArea = vk::Rect2D{
.offset = {0, 0}, .offset = {0, 0},
.extent = {frame->width, frame->height}, .extent = extent,
}; };
render_info.layerCount = 1; render_info.layerCount = 1;
render_info.colorAttachmentCount = 1; render_info.colorAttachmentCount = 1;
@ -224,11 +233,15 @@ void Render(const vk::CommandBuffer& cmdbuf, ::Vulkan::Frame* frame) {
cmdbuf.beginRendering(render_info); cmdbuf.beginRendering(render_info);
Vulkan::RenderDrawData(*draw_data, cmdbuf); Vulkan::RenderDrawData(*draw_data, cmdbuf);
cmdbuf.endRendering(); cmdbuf.endRendering();
if (Config::vkMarkersEnabled()) { if (Config::vkHostMarkersEnabled()) {
cmdbuf.endDebugUtilsLabelEXT(); cmdbuf.endDebugUtilsLabelEXT();
} }
} }
bool MustKeepDrawing() {
return layers.size() > 1 || DebugState.IsShowingDebugMenuBar();
}
} // namespace Core } // namespace Core
void Layer::AddLayer(Layer* layer) { void Layer::AddLayer(Layer* layer) {

View File

@ -3,6 +3,8 @@
#pragma once #pragma once
#include <imgui.h>
#include "video_core/renderer_vulkan/vk_instance.h" #include "video_core/renderer_vulkan/vk_instance.h"
#include "vulkan/vulkan_handles.hpp" #include "vulkan/vulkan_handles.hpp"
@ -24,8 +26,11 @@ void Shutdown(const vk::Device& device);
bool ProcessEvent(SDL_Event* event); bool ProcessEvent(SDL_Event* event);
void NewFrame(); ImGuiID NewFrame(bool is_reusing_frame = false);
void Render(const vk::CommandBuffer& cmdbuf, Vulkan::Frame* frame); void Render(const vk::CommandBuffer& cmdbuf, const vk::ImageView& image_view,
const vk::Extent2D& extent);
bool MustKeepDrawing(); // Force the emulator redraw
} // namespace ImGui::Core } // namespace ImGui::Core

View File

@ -5,6 +5,7 @@
#include <imgui.h> #include <imgui.h>
#include "common/config.h" #include "common/config.h"
#include "core/debug_state.h"
#include "imgui_impl_sdl3.h" #include "imgui_impl_sdl3.h"
// SDL // SDL
@ -26,6 +27,7 @@ struct SdlData {
SDL_Window* window{}; SDL_Window* window{};
SDL_WindowID window_id{}; SDL_WindowID window_id{};
Uint64 time{}; Uint64 time{};
Uint64 nonReusedtime{};
const char* clipboard_text_data{}; const char* clipboard_text_data{};
// IME handling // IME handling
@ -44,6 +46,11 @@ struct SdlData {
ImVector<SDL_Gamepad*> gamepads{}; ImVector<SDL_Gamepad*> gamepads{};
GamepadMode gamepad_mode{}; GamepadMode gamepad_mode{};
bool want_update_gamepads_list{}; bool want_update_gamepads_list{};
// Framerate counting (based on ImGui impl)
std::array<float, 60> framerateSecPerFrame;
int framerateSecPerFrameIdx{};
float framerateSecPerFrameAcc{};
}; };
// Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui // Backend data stored in io.BackendPlatformUserData to allow support for multiple Dear ImGui
@ -785,7 +792,7 @@ static void UpdateGamepads() {
+thumb_dead_zone, +32767); +thumb_dead_zone, +32767);
} }
void NewFrame() { void NewFrame(bool is_reusing_frame) {
SdlData* bd = GetBackendData(); SdlData* bd = GetBackendData();
IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?"); IM_ASSERT(bd != nullptr && "No platform backend to shutdown, or already shutdown?");
ImGuiIO& io = ImGui::GetIO(); ImGuiIO& io = ImGui::GetIO();
@ -798,9 +805,29 @@ void NewFrame() {
if (current_time <= bd->time) if (current_time <= bd->time)
current_time = bd->time + 1; current_time = bd->time + 1;
io.DeltaTime = bd->time > 0 ? (float)((double)(current_time - bd->time) / (double)frequency) io.DeltaTime = bd->time > 0 ? (float)((double)(current_time - bd->time) / (double)frequency)
: (float)(1.0f / 60.0f); : 1.0f / 60.0f;
bd->time = current_time; bd->time = current_time;
if (!is_reusing_frame) {
if (current_time <= bd->nonReusedtime)
current_time = bd->nonReusedtime + 1;
float deltaTime =
bd->nonReusedtime > 0
? (float)((double)(current_time - bd->nonReusedtime) / (double)frequency)
: 1.0f / 60.0f;
bd->nonReusedtime = current_time;
DebugState.FrameDeltaTime = deltaTime;
int& frameIdx = bd->framerateSecPerFrameIdx;
float& framerateSec = bd->framerateSecPerFrame[frameIdx];
float& acc = bd->framerateSecPerFrameAcc;
int count = bd->framerateSecPerFrame.size();
acc += deltaTime - framerateSec;
framerateSec = deltaTime;
frameIdx = (frameIdx + 1) % count;
DebugState.Framerate = acc > 0.0f ? 1.0f / (acc / (float)count) : FLT_MAX;
}
if (bd->mouse_pending_leave_frame && bd->mouse_pending_leave_frame >= ImGui::GetFrameCount() && if (bd->mouse_pending_leave_frame && bd->mouse_pending_leave_frame >= ImGui::GetFrameCount() &&
bd->mouse_buttons_down == 0) { bd->mouse_buttons_down == 0) {
bd->mouse_window_id = 0; bd->mouse_window_id = 0;

View File

@ -14,7 +14,7 @@ namespace ImGui::Sdl {
bool Init(SDL_Window* window); bool Init(SDL_Window* window);
void Shutdown(); void Shutdown();
void NewFrame(); void NewFrame(bool is_reusing);
bool ProcessEvent(const SDL_Event* event); bool ProcessEvent(const SDL_Event* event);
void OnResize(); void OnResize();

View File

@ -57,11 +57,12 @@ struct VkData {
vk::DeviceMemory font_memory{}; vk::DeviceMemory font_memory{};
vk::Image font_image{}; vk::Image font_image{};
vk::ImageView font_view{}; vk::ImageView font_view{};
vk::DescriptorSet font_descriptor_set{}; ImTextureID font_texture{};
vk::CommandBuffer font_command_buffer{}; vk::CommandBuffer font_command_buffer{};
// Render buffers // Render buffers
WindowRenderBuffers render_buffers{}; WindowRenderBuffers render_buffers{};
bool enabled_blending{true};
VkData(const InitInfo init_info) : init_info(init_info) { VkData(const InitInfo init_info) : init_info(init_info) {
render_buffers.count = init_info.image_count; render_buffers.count = init_info.image_count;
@ -252,8 +253,8 @@ void UploadTextureData::Destroy() {
const InitInfo& v = bd->init_info; const InitInfo& v = bd->init_info;
CheckVkErr(v.device.waitIdle()); CheckVkErr(v.device.waitIdle());
RemoveTexture(descriptor_set); RemoveTexture(im_texture);
descriptor_set = VK_NULL_HANDLE; im_texture = nullptr;
v.device.destroyImageView(image_view, v.allocator); v.device.destroyImageView(image_view, v.allocator);
image_view = VK_NULL_HANDLE; image_view = VK_NULL_HANDLE;
@ -264,8 +265,8 @@ void UploadTextureData::Destroy() {
} }
// Register a texture // Register a texture
vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout, ImTextureID AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout,
vk::Sampler sampler) { vk::Sampler sampler) {
VkData* bd = GetBackendData(); VkData* bd = GetBackendData();
const InitInfo& v = bd->init_info; const InitInfo& v = bd->init_info;
@ -303,7 +304,9 @@ vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_lay
}; };
v.device.updateDescriptorSets({write_desc}, {}); v.device.updateDescriptorSets({write_desc}, {});
} }
return descriptor_set; return new Texture{
.descriptor_set = descriptor_set,
};
} }
UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height, UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height,
size_t size) { size_t size) {
@ -370,7 +373,7 @@ UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width,
} }
// Create descriptor set (ImTextureID) // Create descriptor set (ImTextureID)
info.descriptor_set = AddTexture(info.image_view, vk::ImageLayout::eShaderReadOnlyOptimal); info.im_texture = AddTexture(info.image_view, vk::ImageLayout::eShaderReadOnlyOptimal);
// Create Upload Buffer // Create Upload Buffer
{ {
@ -464,10 +467,12 @@ UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width,
return info; return info;
} }
void RemoveTexture(vk::DescriptorSet descriptor_set) { void RemoveTexture(ImTextureID texture) {
IM_ASSERT(texture != nullptr);
VkData* bd = GetBackendData(); VkData* bd = GetBackendData();
const InitInfo& v = bd->init_info; const InitInfo& v = bd->init_info;
v.device.freeDescriptorSets(bd->descriptor_pool, {descriptor_set}); v.device.freeDescriptorSets(bd->descriptor_pool, {texture->descriptor_set});
delete texture;
} }
static void CreateOrResizeBuffer(RenderBuffer& rb, size_t new_size, vk::BufferUsageFlagBits usage) { static void CreateOrResizeBuffer(RenderBuffer& rb, size_t new_size, vk::BufferUsageFlagBits usage) {
@ -679,13 +684,7 @@ void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer,
command_buffer.setScissor(0, 1, &scissor); command_buffer.setScissor(0, 1, &scissor);
// Bind DescriptorSet with font or user texture // Bind DescriptorSet with font or user texture
vk::DescriptorSet desc_set[1]{(VkDescriptorSet)pcmd->TextureId}; vk::DescriptorSet desc_set[1]{pcmd->TextureId->descriptor_set};
if (sizeof(ImTextureID) < sizeof(ImU64)) {
// We don't support texture switches if ImTextureID hasn't been redefined to be
// 64-bit. Do a flaky check that other textures haven't been used.
IM_ASSERT(pcmd->TextureId == (ImTextureID)bd->font_descriptor_set);
desc_set[0] = bd->font_descriptor_set;
}
command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, command_buffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics,
bd->pipeline_layout, 0, {desc_set}, {}); bd->pipeline_layout, 0, {desc_set}, {});
@ -709,7 +708,7 @@ static bool CreateFontsTexture() {
const InitInfo& v = bd->init_info; const InitInfo& v = bd->init_info;
// Destroy existing texture (if any) // Destroy existing texture (if any)
if (bd->font_view || bd->font_image || bd->font_memory || bd->font_descriptor_set) { if (bd->font_view || bd->font_image || bd->font_memory || bd->font_texture) {
CheckVkErr(v.queue.waitIdle()); CheckVkErr(v.queue.waitIdle());
DestroyFontsTexture(); DestroyFontsTexture();
} }
@ -782,7 +781,7 @@ static bool CreateFontsTexture() {
} }
// Create the Descriptor Set: // Create the Descriptor Set:
bd->font_descriptor_set = AddTexture(bd->font_view, vk::ImageLayout::eShaderReadOnlyOptimal); bd->font_texture = AddTexture(bd->font_view, vk::ImageLayout::eShaderReadOnlyOptimal);
// Create the Upload Buffer: // Create the Upload Buffer:
vk::DeviceMemory upload_buffer_memory{}; vk::DeviceMemory upload_buffer_memory{};
@ -874,7 +873,7 @@ static bool CreateFontsTexture() {
} }
// Store our identifier // Store our identifier
io.Fonts->SetTexID(bd->font_descriptor_set); io.Fonts->SetTexID(bd->font_texture);
// End command buffer // End command buffer
vk::SubmitInfo end_info = {}; vk::SubmitInfo end_info = {};
@ -898,9 +897,9 @@ static void DestroyFontsTexture() {
VkData* bd = GetBackendData(); VkData* bd = GetBackendData();
const InitInfo& v = bd->init_info; const InitInfo& v = bd->init_info;
if (bd->font_descriptor_set) { if (bd->font_texture) {
RemoveTexture(bd->font_descriptor_set); RemoveTexture(bd->font_texture);
bd->font_descriptor_set = VK_NULL_HANDLE; bd->font_texture = nullptr;
io.Fonts->SetTexID(nullptr); io.Fonts->SetTexID(nullptr);
} }

View File

@ -10,6 +10,12 @@
struct ImDrawData; struct ImDrawData;
namespace ImGui {
struct Texture {
vk::DescriptorSet descriptor_set{nullptr};
};
} // namespace ImGui
namespace ImGui::Vulkan { namespace ImGui::Vulkan {
struct InitInfo { struct InitInfo {
@ -34,29 +40,32 @@ struct InitInfo {
struct UploadTextureData { struct UploadTextureData {
vk::Image image; vk::Image image;
vk::ImageView image_view; vk::ImageView image_view;
vk::DescriptorSet descriptor_set;
vk::DeviceMemory image_memory; vk::DeviceMemory image_memory;
vk::CommandBuffer command_buffer; // Submit to the queue vk::CommandBuffer command_buffer; // Submit to the queue
vk::Buffer upload_buffer; vk::Buffer upload_buffer;
vk::DeviceMemory upload_buffer_memory; vk::DeviceMemory upload_buffer_memory;
ImTextureID im_texture;
void Upload(); void Upload();
void Destroy(); void Destroy();
}; };
vk::DescriptorSet AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout, ImTextureID AddTexture(vk::ImageView image_view, vk::ImageLayout image_layout,
vk::Sampler sampler = VK_NULL_HANDLE); vk::Sampler sampler = VK_NULL_HANDLE);
UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height, UploadTextureData UploadTexture(const void* data, vk::Format format, u32 width, u32 height,
size_t size); size_t size);
void RemoveTexture(vk::DescriptorSet descriptor_set); void RemoveTexture(ImTextureID descriptor_set);
bool Init(InitInfo info); bool Init(InitInfo info);
void Shutdown(); void Shutdown();
void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer, void RenderDrawData(ImDrawData& draw_data, vk::CommandBuffer command_buffer,
vk::Pipeline pipeline = VK_NULL_HANDLE); vk::Pipeline pipeline = VK_NULL_HANDLE);
void SetBlendEnabled(bool enabled);
} // namespace ImGui::Vulkan } // namespace ImGui::Vulkan

View File

@ -4,6 +4,7 @@
#include <deque> #include <deque>
#include <utility> #include <utility>
#include <imgui.h>
#include "common/assert.h" #include "common/assert.h"
#include "common/config.h" #include "common/config.h"
#include "common/io_file.h" #include "common/io_file.h"
@ -123,7 +124,7 @@ static std::deque<UploadJob> g_upload_list;
namespace Core::TextureManager { namespace Core::TextureManager {
Inner::~Inner() { Inner::~Inner() {
if (upload_data.descriptor_set != nullptr) { if (upload_data.im_texture != nullptr) {
std::unique_lock lk{g_upload_mtx}; std::unique_lock lk{g_upload_mtx};
g_upload_list.emplace_back(UploadJob{ g_upload_list.emplace_back(UploadJob{
.data = this->upload_data, .data = this->upload_data,
@ -239,7 +240,7 @@ void Submit() {
} }
if (upload.core != nullptr) { if (upload.core != nullptr) {
upload.core->upload_data.Upload(); upload.core->upload_data.Upload();
upload.core->texture_id = upload.core->upload_data.descriptor_set; upload.core->texture_id = upload.core->upload_data.im_texture;
if (upload.core->count.fetch_sub(1) == 1) { if (upload.core->count.fetch_sub(1) == 1) {
delete upload.core; delete upload.core;
} }

View File

@ -10,6 +10,55 @@
namespace Input { namespace Input {
using Libraries::Pad::OrbisPadButtonDataOffset;
void State::OnButton(OrbisPadButtonDataOffset button, bool isPressed) {
if (isPressed) {
buttonsState |= button;
} else {
buttonsState &= ~button;
}
}
void State::OnAxis(Axis axis, int value) {
const auto toggle = [&](const auto button) {
if (value > 0) {
buttonsState |= button;
} else {
buttonsState &= ~button;
}
};
switch (axis) {
case Axis::TriggerLeft:
toggle(OrbisPadButtonDataOffset::L2);
break;
case Axis::TriggerRight:
toggle(OrbisPadButtonDataOffset::R2);
break;
default:
break;
}
axes[static_cast<int>(axis)] = value;
}
void State::OnTouchpad(int touchIndex, bool isDown, float x, float y) {
touchpad[touchIndex].state = isDown;
touchpad[touchIndex].x = static_cast<u16>(x * 1920);
touchpad[touchIndex].y = static_cast<u16>(y * 941);
}
void State::OnGyro(const float gyro[3]) {
angularVelocity.x = gyro[0];
angularVelocity.y = gyro[1];
angularVelocity.z = gyro[2];
}
void State::OnAccel(const float accel[3]) {
acceleration.x = accel[0];
acceleration.y = accel[1];
acceleration.z = accel[2];
}
GameController::GameController() { GameController::GameController() {
m_states_num = 0; m_states_num = 0;
m_last_state = State(); m_last_state = State();
@ -75,45 +124,22 @@ void GameController::AddState(const State& state) {
m_states_num++; m_states_num++;
} }
void GameController::CheckButton(int id, Libraries::Pad::OrbisPadButtonDataOffset button, void GameController::CheckButton(int id, OrbisPadButtonDataOffset button, bool is_pressed) {
bool is_pressed) {
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
auto state = GetLastState(); auto state = GetLastState();
state.time = Libraries::Kernel::sceKernelGetProcessTime(); state.time = Libraries::Kernel::sceKernelGetProcessTime();
if (is_pressed) { state.OnButton(button, is_pressed);
state.buttonsState |= button;
} else {
state.buttonsState &= ~button;
}
AddState(state); AddState(state);
} }
void GameController::Axis(int id, Input::Axis axis, int value) { void GameController::Axis(int id, Input::Axis axis, int value) {
using Libraries::Pad::OrbisPadButtonDataOffset;
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
auto state = GetLastState(); auto state = GetLastState();
state.time = Libraries::Kernel::sceKernelGetProcessTime(); state.time = Libraries::Kernel::sceKernelGetProcessTime();
int axis_id = static_cast<int>(axis); state.OnAxis(axis, value);
state.axes[axis_id] = value;
if (axis == Input::Axis::TriggerLeft) {
if (value > 0) {
state.buttonsState |= OrbisPadButtonDataOffset::L2;
} else {
state.buttonsState &= ~OrbisPadButtonDataOffset::L2;
}
}
if (axis == Input::Axis::TriggerRight) {
if (value > 0) {
state.buttonsState |= OrbisPadButtonDataOffset::R2;
} else {
state.buttonsState &= ~OrbisPadButtonDataOffset::R2;
}
}
AddState(state); AddState(state);
} }
@ -124,9 +150,7 @@ void GameController::Gyro(int id, const float gyro[3]) {
state.time = Libraries::Kernel::sceKernelGetProcessTime(); state.time = Libraries::Kernel::sceKernelGetProcessTime();
// Update the angular velocity (gyro data) // Update the angular velocity (gyro data)
state.angularVelocity.x = gyro[0]; // X-axis state.OnGyro(gyro);
state.angularVelocity.y = gyro[1]; // Y-axis
state.angularVelocity.z = gyro[2]; // Z-axis
AddState(state); AddState(state);
} }
@ -136,9 +160,7 @@ void GameController::Acceleration(int id, const float acceleration[3]) {
state.time = Libraries::Kernel::sceKernelGetProcessTime(); state.time = Libraries::Kernel::sceKernelGetProcessTime();
// Update the acceleration values // Update the acceleration values
state.acceleration.x = acceleration[0]; // X-axis state.OnAccel(acceleration);
state.acceleration.y = acceleration[1]; // Y-axis
state.acceleration.z = acceleration[2]; // Z-axis
AddState(state); AddState(state);
} }
@ -211,62 +233,48 @@ void GameController::CalculateOrientation(Libraries::Pad::OrbisFVector3& acceler
} }
void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) { void GameController::SetLightBarRGB(u8 r, u8 g, u8 b) {
if (m_sdl_gamepad != nullptr) { if (!m_engine) {
SDL_SetGamepadLED(m_sdl_gamepad, r, g, b); return;
} }
std::scoped_lock _{m_mutex};
m_engine->SetLightBarRGB(r, g, b);
} }
bool GameController::SetVibration(u8 smallMotor, u8 largeMotor) { void GameController::SetVibration(u8 smallMotor, u8 largeMotor) {
if (m_sdl_gamepad != nullptr) { if (!m_engine) {
return SDL_RumbleGamepad(m_sdl_gamepad, (smallMotor / 255.0f) * 0xFFFF, return;
(largeMotor / 255.0f) * 0xFFFF, -1);
} }
return true; std::scoped_lock _{m_mutex};
m_engine->SetVibration(smallMotor, largeMotor);
} }
void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) { void GameController::SetTouchpadState(int touchIndex, bool touchDown, float x, float y) {
if (touchIndex < 2) { if (touchIndex < 2) {
std::scoped_lock lock{m_mutex}; std::scoped_lock lock{m_mutex};
auto state = GetLastState(); auto state = GetLastState();
state.time = Libraries::Kernel::sceKernelGetProcessTime();
state.touchpad[touchIndex].state = touchDown; state.time = Libraries::Kernel::sceKernelGetProcessTime();
state.touchpad[touchIndex].x = static_cast<u16>(x * 1920); state.OnTouchpad(touchIndex, touchDown, x, y);
state.touchpad[touchIndex].y = static_cast<u16>(y * 941);
AddState(state); AddState(state);
} }
} }
void GameController::TryOpenSDLController() { void GameController::SetEngine(std::unique_ptr<Engine> engine) {
if (m_sdl_gamepad == nullptr || !SDL_GamepadConnected(m_sdl_gamepad)) { std::scoped_lock _{m_mutex};
int gamepad_count; m_engine = std::move(engine);
SDL_JoystickID* gamepads = SDL_GetGamepads(&gamepad_count); if (m_engine) {
m_sdl_gamepad = gamepad_count > 0 ? SDL_OpenGamepad(gamepads[0]) : nullptr; m_engine->Init();
if (Config::getIsMotionControlsEnabled()) {
if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_GYRO, true)) {
gyro_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_GYRO);
LOG_INFO(Input, "Gyro initialized, poll rate: {}", gyro_poll_rate);
} else {
LOG_ERROR(Input, "Failed to initialize gyro controls for gamepad");
}
if (SDL_SetGamepadSensorEnabled(m_sdl_gamepad, SDL_SENSOR_ACCEL, true)) {
accel_poll_rate = SDL_GetGamepadSensorDataRate(m_sdl_gamepad, SDL_SENSOR_ACCEL);
LOG_INFO(Input, "Accel initialized, poll rate: {}", accel_poll_rate);
} else {
LOG_ERROR(Input, "Failed to initialize accel controls for gamepad");
}
}
SDL_free(gamepads);
SetLightBarRGB(0, 0, 255);
} }
} }
Engine* GameController::GetEngine() {
return m_engine.get();
}
u32 GameController::Poll() { u32 GameController::Poll() {
std::scoped_lock lock{m_mutex};
if (m_connected) { if (m_connected) {
std::scoped_lock lock{m_mutex};
auto time = Libraries::Kernel::sceKernelGetProcessTime(); auto time = Libraries::Kernel::sceKernelGetProcessTime();
if (m_states_num == 0) { if (m_states_num == 0) {
auto diff = (time - m_last_state.time) / 1000; auto diff = (time - m_last_state.time) / 1000;

View File

@ -3,12 +3,12 @@
#pragma once #pragma once
#include <algorithm>
#include <memory>
#include <mutex> #include <mutex>
#include "common/types.h" #include "common/types.h"
#include "core/libraries/pad/pad.h" #include "core/libraries/pad/pad.h"
struct SDL_Gamepad;
namespace Input { namespace Input {
enum class Axis { enum class Axis {
@ -28,7 +28,14 @@ struct TouchpadEntry {
u16 y{}; u16 y{};
}; };
struct State { class State {
public:
void OnButton(Libraries::Pad::OrbisPadButtonDataOffset, bool);
void OnAxis(Axis, int);
void OnTouchpad(int touchIndex, bool isDown, float x, float y);
void OnGyro(const float[3]);
void OnAccel(const float[3]);
Libraries::Pad::OrbisPadButtonDataOffset buttonsState{}; Libraries::Pad::OrbisPadButtonDataOffset buttonsState{};
u64 time = 0; u64 time = 0;
int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0}; int axes[static_cast<int>(Axis::AxisMax)] = {128, 128, 128, 128, 0, 0};
@ -38,9 +45,19 @@ struct State {
Libraries::Pad::OrbisFQuaternion orientation = {0.0f, 0.0f, 0.0f, 1.0f}; Libraries::Pad::OrbisFQuaternion orientation = {0.0f, 0.0f, 0.0f, 1.0f};
}; };
class Engine {
public:
virtual ~Engine() = default;
virtual void Init() = 0;
virtual void SetLightBarRGB(u8 r, u8 g, u8 b) = 0;
virtual void SetVibration(u8 smallMotor, u8 largeMotor) = 0;
virtual State ReadState() = 0;
virtual float GetAccelPollRate() const = 0;
virtual float GetGyroPollRate() const = 0;
};
inline int GetAxis(int min, int max, int value) { inline int GetAxis(int min, int max, int value) {
int v = (255 * (value - min)) / (max - min); return std::clamp((255 * (value - min)) / (max - min), 0, 255);
return (v < 0 ? 0 : (v > 255 ? 255 : v));
} }
constexpr u32 MAX_STATES = 64; constexpr u32 MAX_STATES = 64;
@ -59,13 +76,12 @@ public:
void Gyro(int id, const float gyro[3]); void Gyro(int id, const float gyro[3]);
void Acceleration(int id, const float acceleration[3]); void Acceleration(int id, const float acceleration[3]);
void SetLightBarRGB(u8 r, u8 g, u8 b); void SetLightBarRGB(u8 r, u8 g, u8 b);
bool SetVibration(u8 smallMotor, u8 largeMotor); void SetVibration(u8 smallMotor, u8 largeMotor);
void SetTouchpadState(int touchIndex, bool touchDown, float x, float y); void SetTouchpadState(int touchIndex, bool touchDown, float x, float y);
void TryOpenSDLController(); void SetEngine(std::unique_ptr<Engine>);
Engine* GetEngine();
u32 Poll(); u32 Poll();
float gyro_poll_rate;
float accel_poll_rate;
static void CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration, static void CalculateOrientation(Libraries::Pad::OrbisFVector3& acceleration,
Libraries::Pad::OrbisFVector3& angularVelocity, Libraries::Pad::OrbisFVector3& angularVelocity,
float deltaTime, float deltaTime,
@ -85,7 +101,7 @@ private:
std::array<State, MAX_STATES> m_states; std::array<State, MAX_STATES> m_states;
std::array<StateInternal, MAX_STATES> m_private; std::array<StateInternal, MAX_STATES> m_private;
SDL_Gamepad* m_sdl_gamepad = nullptr; std::unique_ptr<Engine> m_engine = nullptr;
}; };
} // namespace Input } // namespace Input

View File

@ -29,6 +29,7 @@ int main(int argc, char* argv[]) {
bool has_game_argument = false; bool has_game_argument = false;
std::string game_path; std::string game_path;
std::vector<std::string> game_args{};
// Map of argument strings to lambda functions // Map of argument strings to lambda functions
std::unordered_map<std::string, std::function<void(int&)>> arg_map = { std::unordered_map<std::string, std::function<void(int&)>> arg_map = {
@ -37,6 +38,9 @@ int main(int argc, char* argv[]) {
std::cout << "Usage: shadps4 [options] <elf or eboot.bin path>\n" std::cout << "Usage: shadps4 [options] <elf or eboot.bin path>\n"
"Options:\n" "Options:\n"
" -g, --game <path|ID> Specify game path to launch\n" " -g, --game <path|ID> Specify game path to launch\n"
" -- ... Parameters passed to the game ELF. "
"Needs to be at the end of the line, and everything after \"--\" is a "
"game argument.\n"
" -p, --patch <patch_file> Apply specified patch file\n" " -p, --patch <patch_file> Apply specified patch file\n"
" -f, --fullscreen <true|false> Specify window initial fullscreen " " -f, --fullscreen <true|false> Specify window initial fullscreen "
"state. Does not overwrite the config file.\n" "state. Does not overwrite the config file.\n"
@ -126,6 +130,21 @@ int main(int argc, char* argv[]) {
// Assume the last argument is the game file if not specified via -g/--game // Assume the last argument is the game file if not specified via -g/--game
game_path = argv[i]; game_path = argv[i];
has_game_argument = true; has_game_argument = true;
} else if (std::string(argv[i]) == "--") {
if (i + 1 == argc) {
std::cerr << "Warning: -- is set, but no game arguments are added!\n";
break;
}
for (int j = i + 1; j < argc; j++) {
game_args.push_back(argv[j]);
}
break;
} else if (i + 1 < argc && std::string(argv[i + 1]) == "--") {
if (!has_game_argument) {
game_path = argv[i];
has_game_argument = true;
}
break;
} else { } else {
std::cerr << "Unknown argument: " << cur_arg << ", see --help for info.\n"; std::cerr << "Unknown argument: " << cur_arg << ", see --help for info.\n";
return 1; return 1;
@ -166,7 +185,7 @@ int main(int argc, char* argv[]) {
// Run the emulator with the resolved eboot path // Run the emulator with the resolved eboot path
Core::Emulator emulator; Core::Emulator emulator;
emulator.Run(eboot_path); emulator.Run(eboot_path, game_args);
return 0; return 0;
} }

View File

@ -188,8 +188,12 @@ void CheatsPatches::setupUI() {
} }
}); });
QPushButton* closeButton = new QPushButton(tr("Close"));
connect(closeButton, &QPushButton::clicked, [this]() { QWidget::close(); });
controlLayout->addWidget(downloadButton); controlLayout->addWidget(downloadButton);
controlLayout->addWidget(deleteCheatButton); controlLayout->addWidget(deleteCheatButton);
controlLayout->addWidget(closeButton);
cheatsLayout->addLayout(controlLayout); cheatsLayout->addLayout(controlLayout);
cheatsTab->setLayout(cheatsLayout); cheatsTab->setLayout(cheatsLayout);
@ -464,6 +468,8 @@ void CheatsPatches::onSaveButtonClicked() {
} else { } else {
QMessageBox::information(this, tr("Success"), tr("Options saved successfully.")); QMessageBox::information(this, tr("Success"), tr("Options saved successfully."));
} }
QWidget::close();
} }
QCheckBox* CheatsPatches::findCheckBoxByName(const QString& name) { QCheckBox* CheatsPatches::findCheckBoxByName(const QString& name) {

View File

@ -33,6 +33,7 @@ int main(int argc, char* argv[]) {
bool has_command_line_argument = argc > 1; bool has_command_line_argument = argc > 1;
bool show_gui = false, has_game_argument = false; bool show_gui = false, has_game_argument = false;
std::string game_path; std::string game_path;
std::vector<std::string> game_args{};
// Map of argument strings to lambda functions // Map of argument strings to lambda functions
std::unordered_map<std::string, std::function<void(int&)>> arg_map = { std::unordered_map<std::string, std::function<void(int&)>> arg_map = {
@ -43,6 +44,9 @@ int main(int argc, char* argv[]) {
" No arguments: Opens the GUI.\n" " No arguments: Opens the GUI.\n"
" -g, --game <path|ID> Specify <eboot.bin or elf path> or " " -g, --game <path|ID> Specify <eboot.bin or elf path> or "
"<game ID (CUSAXXXXX)> to launch\n" "<game ID (CUSAXXXXX)> to launch\n"
" -- ... Parameters passed to the game ELF. "
"Needs to be at the end of the line, and everything after \"--\" is a "
"game argument.\n"
" -p, --patch <patch_file> Apply specified patch file\n" " -p, --patch <patch_file> Apply specified patch file\n"
" -s, --show-gui Show the GUI\n" " -s, --show-gui Show the GUI\n"
" -f, --fullscreen <true|false> Specify window initial fullscreen " " -f, --fullscreen <true|false> Specify window initial fullscreen "
@ -131,6 +135,20 @@ int main(int argc, char* argv[]) {
// Assume the last argument is the game file if not specified via -g/--game // Assume the last argument is the game file if not specified via -g/--game
game_path = argv[i]; game_path = argv[i];
has_game_argument = true; has_game_argument = true;
} else if (std::string(argv[i]) == "--") {
if (i + 1 == argc) {
std::cerr << "Warning: -- is set, but no game arguments are added!\n";
break;
}
for (int j = i + 1; j < argc; j++) {
game_args.push_back(argv[j]);
}
break;
} else if (i + 1 < argc && std::string(argv[i + 1]) == "--") {
if (!has_game_argument) {
game_path = argv[i];
has_game_argument = true;
}
} else { } else {
std::cerr << "Unknown argument: " << cur_arg << ", see --help for info.\n"; std::cerr << "Unknown argument: " << cur_arg << ", see --help for info.\n";
return 1; return 1;
@ -181,7 +199,7 @@ int main(int argc, char* argv[]) {
// Run the emulator with the resolved game path // Run the emulator with the resolved game path
Core::Emulator emulator; Core::Emulator emulator;
emulator.Run(game_file_path.string()); emulator.Run(game_file_path.string(), game_args);
if (!show_gui) { if (!show_gui) {
return 0; // Exit after running the emulator without showing the GUI return 0; // Exit after running the emulator without showing the GUI
} }

View File

@ -247,6 +247,12 @@ void MainWindow::CreateConnects() {
} }
}); });
connect(ui->shadFolderAct, &QAction::triggered, this, [this]() {
QString userPath;
Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir));
QDesktopServices::openUrl(QUrl::fromLocalFile(userPath));
});
connect(ui->playButton, &QPushButton::clicked, this, &MainWindow::StartGame); connect(ui->playButton, &QPushButton::clicked, this, &MainWindow::StartGame);
connect(m_game_grid_frame.get(), &QTableWidget::cellDoubleClicked, this, connect(m_game_grid_frame.get(), &QTableWidget::cellDoubleClicked, this,
&MainWindow::StartGame); &MainWindow::StartGame);
@ -982,6 +988,7 @@ QIcon MainWindow::RecolorIcon(const QIcon& icon, bool isWhite) {
void MainWindow::SetUiIcons(bool isWhite) { void MainWindow::SetUiIcons(bool isWhite) {
ui->bootInstallPkgAct->setIcon(RecolorIcon(ui->bootInstallPkgAct->icon(), isWhite)); ui->bootInstallPkgAct->setIcon(RecolorIcon(ui->bootInstallPkgAct->icon(), isWhite));
ui->bootGameAct->setIcon(RecolorIcon(ui->bootGameAct->icon(), isWhite)); ui->bootGameAct->setIcon(RecolorIcon(ui->bootGameAct->icon(), isWhite));
ui->shadFolderAct->setIcon(RecolorIcon(ui->shadFolderAct->icon(), isWhite));
ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite)); ui->exitAct->setIcon(RecolorIcon(ui->exitAct->icon(), isWhite));
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
ui->updaterAct->setIcon(RecolorIcon(ui->updaterAct->icon(), isWhite)); ui->updaterAct->setIcon(RecolorIcon(ui->updaterAct->icon(), isWhite));

View File

@ -12,6 +12,7 @@ public:
QAction* bootInstallPkgAct; QAction* bootInstallPkgAct;
QAction* bootGameAct; QAction* bootGameAct;
QAction* addElfFolderAct; QAction* addElfFolderAct;
QAction* shadFolderAct;
QAction* exitAct; QAction* exitAct;
QAction* showGameListAct; QAction* showGameListAct;
QAction* refreshGameListAct; QAction* refreshGameListAct;
@ -89,6 +90,9 @@ public:
addElfFolderAct = new QAction(MainWindow); addElfFolderAct = new QAction(MainWindow);
addElfFolderAct->setObjectName("addElfFolderAct"); addElfFolderAct->setObjectName("addElfFolderAct");
addElfFolderAct->setIcon(QIcon(":images/folder_icon.png")); addElfFolderAct->setIcon(QIcon(":images/folder_icon.png"));
shadFolderAct = new QAction(MainWindow);
shadFolderAct->setObjectName("shadFolderAct");
shadFolderAct->setIcon(QIcon(":images/folder_icon.png"));
exitAct = new QAction(MainWindow); exitAct = new QAction(MainWindow);
exitAct->setObjectName("exitAct"); exitAct->setObjectName("exitAct");
exitAct->setIcon(QIcon(":images/exit_icon.png")); exitAct->setIcon(QIcon(":images/exit_icon.png"));
@ -274,7 +278,9 @@ public:
menuBar->addAction(menuHelp->menuAction()); menuBar->addAction(menuHelp->menuAction());
menuFile->addAction(bootInstallPkgAct); menuFile->addAction(bootInstallPkgAct);
menuFile->addAction(bootGameAct); menuFile->addAction(bootGameAct);
menuFile->addSeparator();
menuFile->addAction(addElfFolderAct); menuFile->addAction(addElfFolderAct);
menuFile->addAction(shadFolderAct);
menuFile->addSeparator(); menuFile->addSeparator();
menuFile->addAction(menuRecent->menuAction()); menuFile->addAction(menuRecent->menuAction());
menuFile->addSeparator(); menuFile->addSeparator();
@ -333,6 +339,8 @@ public:
"MainWindow", "Install application from a .pkg file", nullptr)); "MainWindow", "Install application from a .pkg file", nullptr));
#endif // QT_CONFIG(tooltip) #endif // QT_CONFIG(tooltip)
menuRecent->setTitle(QCoreApplication::translate("MainWindow", "Recent Games", nullptr)); menuRecent->setTitle(QCoreApplication::translate("MainWindow", "Recent Games", nullptr));
shadFolderAct->setText(
QCoreApplication::translate("MainWindow", "Open shadPS4 Folder", nullptr));
exitAct->setText(QCoreApplication::translate("MainWindow", "Exit", nullptr)); exitAct->setText(QCoreApplication::translate("MainWindow", "Exit", nullptr));
#if QT_CONFIG(tooltip) #if QT_CONFIG(tooltip)
exitAct->setToolTip(QCoreApplication::translate("MainWindow", "Exit shadPS4", nullptr)); exitAct->setToolTip(QCoreApplication::translate("MainWindow", "Exit shadPS4", nullptr));

View File

@ -65,6 +65,7 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
: QDialog(parent), ui(new Ui::SettingsDialog) { : QDialog(parent), ui(new Ui::SettingsDialog) {
ui->setupUi(this); ui->setupUi(this);
ui->tabWidgetSettings->setUsesScrollButtons(false); ui->tabWidgetSettings->setUsesScrollButtons(false);
initialHeight = this->height(); initialHeight = this->height();
const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir); const auto config_dir = Common::FS::GetUserPath(Common::FS::PathType::UserDir);
@ -150,7 +151,6 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
}); });
#else #else
ui->updaterGroupBox->setVisible(false); ui->updaterGroupBox->setVisible(false);
ui->GUIgroupBox->setMaximumSize(265, 16777215);
#endif #endif
connect(ui->updateCompatibilityButton, &QPushButton::clicked, this, connect(ui->updateCompatibilityButton, &QPushButton::clicked, this,
[this, parent, m_compat_info]() { [this, parent, m_compat_info]() {
@ -169,6 +169,11 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
}); });
} }
// Gui TAB
{
connect(ui->chooseHomeTabComboBox, &QComboBox::currentTextChanged, this,
[](const QString& hometab) { Config::setChooseHomeTab(hometab.toStdString()); });
}
// Input TAB // Input TAB
{ {
connect(ui->hideCursorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, connect(ui->hideCursorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
@ -202,6 +207,21 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
delete selected_item; delete selected_item;
} }
}); });
connect(ui->browseButton, &QPushButton::clicked, this, [this]() {
const auto save_data_path = Config::GetSaveDataPath();
QString initial_path;
Common::FS::PathToQString(initial_path, save_data_path);
QString save_data_path_string =
QFileDialog::getExistingDirectory(this, tr("Directory to save data"), initial_path);
auto file_path = Common::FS::PathFromQString(save_data_path_string);
if (!file_path.empty()) {
Config::setSaveDataPath(file_path);
ui->currentSaveDataPath->setText(save_data_path_string);
}
});
} }
// DEBUG TAB // DEBUG TAB
@ -231,7 +251,7 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
#ifdef ENABLE_UPDATER #ifdef ENABLE_UPDATER
ui->updaterGroupBox->installEventFilter(this); ui->updaterGroupBox->installEventFilter(this);
#endif #endif
ui->GUIgroupBox->installEventFilter(this); ui->GUIMusicGroupBox->installEventFilter(this);
ui->disableTrophycheckBox->installEventFilter(this); ui->disableTrophycheckBox->installEventFilter(this);
ui->enableCompatibilityCheckBox->installEventFilter(this); ui->enableCompatibilityCheckBox->installEventFilter(this);
ui->checkCompatibilityOnStartupCheckBox->installEventFilter(this); ui->checkCompatibilityOnStartupCheckBox->installEventFilter(this);
@ -256,6 +276,10 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices,
ui->addFolderButton->installEventFilter(this); ui->addFolderButton->installEventFilter(this);
ui->removeFolderButton->installEventFilter(this); ui->removeFolderButton->installEventFilter(this);
ui->saveDataGroupBox->installEventFilter(this);
ui->currentSaveDataPath->installEventFilter(this);
ui->browseButton->installEventFilter(this);
// Debug // Debug
ui->debugDump->installEventFilter(this); ui->debugDump->installEventFilter(this);
ui->vkValidationCheckBox->installEventFilter(this); ui->vkValidationCheckBox->installEventFilter(this);
@ -286,6 +310,11 @@ void SettingsDialog::LoadValuesFromConfig() {
const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 9, const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 9,
15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 30, 28}; 15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 30, 28};
const auto save_data_path = Config::GetSaveDataPath();
QString save_data_path_string;
Common::FS::PathToQString(save_data_path_string, save_data_path);
ui->currentSaveDataPath->setText(save_data_path_string);
ui->consoleLanguageComboBox->setCurrentIndex( ui->consoleLanguageComboBox->setCurrentIndex(
std::distance(languageIndexes.begin(), std::distance(languageIndexes.begin(),
std::find(languageIndexes.begin(), languageIndexes.end(), std::find(languageIndexes.begin(), languageIndexes.end(),
@ -349,6 +378,15 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->updateComboBox->setCurrentText(QString::fromStdString(updateChannel)); ui->updateComboBox->setCurrentText(QString::fromStdString(updateChannel));
#endif #endif
std::string chooseHomeTab = toml::find_or<std::string>(data, "General", "chooseHomeTab", "");
ui->chooseHomeTabComboBox->setCurrentText(QString::fromStdString(chooseHomeTab));
QStringList tabNames = {tr("General"), tr("Gui"), tr("Graphics"), tr("User"),
tr("Input"), tr("Paths"), tr("Debug")};
QString chooseHomeTabQString = QString::fromStdString(chooseHomeTab);
int indexTab = tabNames.indexOf(chooseHomeTabQString);
indexTab = (indexTab == -1) ? 0 : indexTab;
ui->tabWidgetSettings->setCurrentIndex(indexTab);
QString backButtonBehavior = QString::fromStdString( QString backButtonBehavior = QString::fromStdString(
toml::find_or<std::string>(data, "Input", "backButtonBehavior", "left")); toml::find_or<std::string>(data, "Input", "backButtonBehavior", "left"));
int index = ui->backButtonBehaviorComboBox->findData(backButtonBehavior); int index = ui->backButtonBehaviorComboBox->findData(backButtonBehavior);
@ -452,8 +490,8 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
} else if (elementName == "updaterGroupBox") { } else if (elementName == "updaterGroupBox") {
text = tr("updaterGroupBox"); text = tr("updaterGroupBox");
#endif #endif
} else if (elementName == "GUIgroupBox") { } else if (elementName == "GUIMusicGroupBox") {
text = tr("GUIgroupBox"); text = tr("GUIMusicGroupBox");
} else if (elementName == "disableTrophycheckBox") { } else if (elementName == "disableTrophycheckBox") {
text = tr("disableTrophycheckBox"); text = tr("disableTrophycheckBox");
} else if (elementName == "enableCompatibilityCheckBox") { } else if (elementName == "enableCompatibilityCheckBox") {
@ -497,6 +535,13 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
text = tr("removeFolderButton"); text = tr("removeFolderButton");
} }
// Save Data
if (elementName == "saveDataGroupBox" || elementName == "currentSaveDataPath") {
text = tr("saveDataBox");
} else if (elementName == "browseButton") {
text = tr("browseButton");
}
// Debug // Debug
if (elementName == "debugDump") { if (elementName == "debugDump") {
text = tr("debugDump"); text = tr("debugDump");
@ -522,22 +567,6 @@ bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) {
} else { } else {
ui->descriptionText->setText(defaultTextEdit); ui->descriptionText->setText(defaultTextEdit);
} }
// if the text exceeds the size of the box, it will increase the size
QRect currentGeometry = this->geometry();
int newWidth = currentGeometry.width();
int documentHeight = ui->descriptionText->document()->size().height();
int visibleHeight = ui->descriptionText->viewport()->height();
if (documentHeight > visibleHeight) {
ui->descriptionText->setMaximumSize(16777215, 110);
this->setGeometry(currentGeometry.x(), currentGeometry.y(), newWidth,
currentGeometry.height() + 40);
} else {
ui->descriptionText->setMaximumSize(16777215, 70);
this->setGeometry(currentGeometry.x(), currentGeometry.y(), newWidth,
initialHeight);
}
return true; return true;
} }
} }
@ -577,6 +606,7 @@ void SettingsDialog::UpdateSettings() {
Config::setRdocEnabled(ui->rdocCheckBox->isChecked()); Config::setRdocEnabled(ui->rdocCheckBox->isChecked());
Config::setAutoUpdate(ui->updateCheckBox->isChecked()); Config::setAutoUpdate(ui->updateCheckBox->isChecked());
Config::setUpdateChannel(ui->updateComboBox->currentText().toStdString()); Config::setUpdateChannel(ui->updateComboBox->currentText().toStdString());
Config::setChooseHomeTab(ui->chooseHomeTabComboBox->currentText().toStdString());
Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked()); Config::setCompatibilityEnabled(ui->enableCompatibilityCheckBox->isChecked());
Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked()); Config::setCheckCompatibilityOnStartup(ui->checkCompatibilityOnStartupCheckBox->isChecked());
@ -619,4 +649,4 @@ void SettingsDialog::ResetInstallFolders() {
} }
Config::setGameInstallDirs(settings_install_dirs_config); Config::setGameInstallDirs(settings_install_dirs_config);
} }
} }

File diff suppressed because it is too large Load Diff

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>الألعاب الأخيرة</translation> <translation>الألعاب الأخيرة</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>خروج</translation> <translation>خروج</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>تمكين ملء الشاشة</translation> <translation>تمكين ملء الشاشة</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>وضع ملء الشاشة</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>علامة التبويب الافتراضية عند فتح الإعدادات</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>عرض حجم اللعبة في القائمة</translation> <translation>عرض حجم اللعبة في القائمة</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>الرسومات</translation> <translation>الرسومات</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>واجهة</translation>
</message>
<message>
<source>User</source>
<translation>مستخدم</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>جهاز الرسومات</translation> <translation>جهاز الرسومات</translation>
@ -801,7 +821,7 @@
<translation>تحديث: Release: إصدارات رسمية تصدر شهريًا، قد تكون قديمة بعض الشيء، لكنها أكثر استقرارًا واختبارًا. Nightly: إصدارات تطوير تحتوي على أحدث الميزات والإصلاحات، لكنها قد تحتوي على أخطاء وأقل استقرارًا.</translation> <translation>تحديث: Release: إصدارات رسمية تصدر شهريًا، قد تكون قديمة بعض الشيء، لكنها أكثر استقرارًا واختبارًا. Nightly: إصدارات تطوير تحتوي على أحدث الميزات والإصلاحات، لكنها قد تحتوي على أخطاء وأقل استقرارًا.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>تشغيل موسيقى العنوان:\nإذا كانت اللعبة تدعم ذلك، قم بتمكين تشغيل موسيقى خاصة عند اختيار اللعبة في واجهة المستخدم.</translation> <translation>تشغيل موسيقى العنوان:\nإذا كانت اللعبة تدعم ذلك، قم بتمكين تشغيل موسيقى خاصة عند اختيار اللعبة في واجهة المستخدم.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Fuldskærmstilstand</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Standardfaneblad ved åbning af indstillinger</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Vis vis spilstørrelse i listen</translation> <translation>Vis vis spilstørrelse i listen</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interface</translation>
</message>
<message>
<source>User</source>
<translation>Bruger</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Opdatering:\nRelease: Officielle builds, der frigives månedligt, som kan være meget ældre, men mere stabile og testet.\nNightly: Udviklerbuilds med de nyeste funktioner og rettelser, men som kan indeholde fejl og være mindre stabile.</translation> <translation>Opdatering:\nRelease: Officielle builds, der frigives månedligt, som kan være meget ældre, men mere stabile og testet.\nNightly: Udviklerbuilds med de nyeste funktioner og rettelser, men som kan indeholde fejl og være mindre stabile.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Titelsmusikafspilning:\nHvis spillet understøtter det, aktiver speciel musik, når spillet vælges i brugergrænsefladen.</translation> <translation>Titelsmusikafspilning:\nHvis spillet understøtter det, aktiver speciel musik, når spillet vælges i brugergrænsefladen.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Zuletzt gespielt</translation> <translation>Zuletzt gespielt</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Beenden</translation> <translation>Beenden</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Vollbild aktivieren</translation> <translation>Vollbild aktivieren</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Vollbildmodus</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Standardregisterkarte beim Öffnen der Einstellungen</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Zeigen Sie die Spielgröße in der Liste</translation> <translation>Zeigen Sie die Spielgröße in der Liste</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafik</translation> <translation>Grafik</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Benutzeroberfläche</translation>
</message>
<message>
<source>User</source>
<translation>Benutzer</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Grafikgerät</translation> <translation>Grafikgerät</translation>
@ -801,7 +821,7 @@
<translation>Update:\nRelease: Offizielle Builds, die monatlich veröffentlicht werden, können viel älter sein, aber stabiler und getestet.\nNightly: Entwickler-Builds, die die neuesten Funktionen und Fehlerbehebungen enthalten, aber Fehler enthalten und weniger stabil sein können.</translation> <translation>Update:\nRelease: Offizielle Builds, die monatlich veröffentlicht werden, können viel älter sein, aber stabiler und getestet.\nNightly: Entwickler-Builds, die die neuesten Funktionen und Fehlerbehebungen enthalten, aber Fehler enthalten und weniger stabil sein können.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Wiedergabe der Titelmusik:\nWenn das Spiel dies unterstützt, wird beim Auswählen des Spiels in der Benutzeroberfläche spezielle Musik abgespielt.</translation> <translation>Wiedergabe der Titelmusik:\nWenn das Spiel dies unterstützt, wird beim Auswählen des Spiels in der Benutzeroberfläche spezielle Musik abgespielt.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Λειτουργία Πλήρους Οθόνης</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Προεπιλεγμένη καρτέλα κατά την ανοίγμα των ρυθμίσεων</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Εμφάνιση Μεγέθους Παιχνιδιού στη Λίστα</translation> <translation>Εμφάνιση Μεγέθους Παιχνιδιού στη Λίστα</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Διεπαφή</translation>
</message>
<message>
<source>User</source>
<translation>Χρήστης</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Ενημερώσεις:\nRelease: Επίσημες εκδόσεις που κυκλοφορούν μηνιαίως, είναι παλαιότερες αλλά πιο σταθερές και δοκιμασμένες.\nNightly: Εκδόσεις προγραμματιστών με νέες δυνατότητες και διορθώσεις, αλλά μπορεί να περιέχουν σφάλματα και να είναι λιγότερο σταθερές.</translation> <translation>Ενημερώσεις:\nRelease: Επίσημες εκδόσεις που κυκλοφορούν μηνιαίως, είναι παλαιότερες αλλά πιο σταθερές και δοκιμασμένες.\nNightly: Εκδόσεις προγραμματιστών με νέες δυνατότητες και διορθώσεις, αλλά μπορεί να περιέχουν σφάλματα και να είναι λιγότερο σταθερές.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Αναπαραγωγή Μουσικής Τίτλων:\nΕάν το παιχνίδι το υποστηρίζει, ενεργοποιεί ειδική μουσική κατά την επιλογή του παιχνιδιού από τη διεπαφή χρήστη.</translation> <translation>Αναπαραγωγή Μουσικής Τίτλων:\nΕάν το παιχνίδι το υποστηρίζει, ενεργοποιεί ειδική μουσική κατά την επιλογή του παιχνιδιού από τη διεπαφή χρήστη.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Fullscreen Mode</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Default tab when opening settings</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Show Game Size In List</translation> <translation>Show Game Size In List</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Gui</translation>
</message>
<message>
<source>User</source>
<translation>User</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable.</translation> <translation>Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</translation> <translation>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</translation>
</message> </message>
<message> <message>
@ -908,6 +928,14 @@
<source>rdocCheckBox</source> <source>rdocCheckBox</source>
<translation>Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame.</translation> <translation>Enable RenderDoc Debugging:\nIf enabled, the emulator will provide compatibility with Renderdoc to allow capture and analysis of the currently rendered frame.</translation>
</message> </message>
<message>
<source>saveDataBox</source>
<translation>Save Data Path:\nThe folder where game save data will be saved.</translation>
</message>
<message>
<source>browseButton</source>
<translation>Browse:\nBrowse for a folder to set as the save data path.</translation>
</message>
</context> </context>
<context> <context>
<name>CheatsPatches</name> <name>CheatsPatches</name>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Juegos recientes</translation> <translation>Juegos recientes</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Salir</translation> <translation>Salir</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Habilitar pantalla completa</translation> <translation>Habilitar pantalla completa</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Modo de Pantalla Completa</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Pestaña predeterminada al abrir la configuración</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Mostrar Tamaño del Juego en la Lista</translation> <translation>Mostrar Tamaño del Juego en la Lista</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Gráficos</translation> <translation>Gráficos</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interfaz</translation>
</message>
<message>
<source>User</source>
<translation>Usuario</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Dispositivo gráfico</translation> <translation>Dispositivo gráfico</translation>
@ -801,7 +821,7 @@
<translation>Actualización:\nRelease: Versiones oficiales lanzadas cada mes que pueden estar muy desactualizadas, pero son más confiables y están probadas.\nNightly: Versiones de desarrollo que tienen todas las últimas funciones y correcciones, pero pueden contener errores y son menos estables.</translation> <translation>Actualización:\nRelease: Versiones oficiales lanzadas cada mes que pueden estar muy desactualizadas, pero son más confiables y están probadas.\nNightly: Versiones de desarrollo que tienen todas las últimas funciones y correcciones, pero pueden contener errores y son menos estables.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Reproducir Música del Título:\nSi un juego lo admite, habilita la reproducción de música especial al seleccionar el juego en la interfaz gráfica.</translation> <translation>Reproducir Música del Título:\nSi un juego lo admite, habilita la reproducción de música especial al seleccionar el juego en la interfaz gráfica.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>بازی های اخیر</translation> <translation>بازی های اخیر</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>خروج</translation> <translation>خروج</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>تمام صفحه</translation> <translation>تمام صفحه</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>حالت تمام صفحه</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>فعالسازی پوشه جداگانه برای بهروزرسانی</translation> <translation>فعالسازی پوشه جداگانه برای بهروزرسانی</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>زبان پیشفرض هنگام باز کردن تنظیمات</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>نمایش اندازه بازی در لیست</translation> <translation>نمایش اندازه بازی در لیست</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>گرافیک</translation> <translation>گرافیک</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>رابط کاربری</translation>
</message>
<message>
<source>User</source>
<translation>کاربر</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>کارت گرافیک مورداستفاده</translation> <translation>کارت گرافیک مورداستفاده</translation>
@ -801,7 +821,7 @@
<translation>بهروزرسانی:\nانتشار: نسخه‌های رسمی که هر ماه منتشر میشوند و ممکن است بسیار قدیمی باشند، اما پایدارتر و تست شدهتر هستند.\nشبانه: نسخه‌های توسعهای که شامل جدیدترین ویژگیها و اصلاحات هستند، اما ممکن است دارای اشکال باشند و کمتر پایدار باشند.</translation> <translation>بهروزرسانی:\nانتشار: نسخه‌های رسمی که هر ماه منتشر میشوند و ممکن است بسیار قدیمی باشند، اما پایدارتر و تست شدهتر هستند.\nشبانه: نسخه‌های توسعهای که شامل جدیدترین ویژگیها و اصلاحات هستند، اما ممکن است دارای اشکال باشند و کمتر پایدار باشند.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>پخش موسیقی عنوان:\nIدر صورتی که بازی از آن پشتیبانی کند، پخش موسیقی ویژه هنگام انتخاب بازی در رابط کاربری را فعال میکند.</translation> <translation>پخش موسیقی عنوان:\nIدر صورتی که بازی از آن پشتیبانی کند، پخش موسیقی ویژه هنگام انتخاب بازی در رابط کاربری را فعال میکند.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Viimeisimmät Pelit</translation> <translation>Viimeisimmät Pelit</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Sulje</translation> <translation>Sulje</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Ota Käyttöön Koko Ruudun Tila</translation> <translation>Ota Käyttöön Koko Ruudun Tila</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Koko näytön tila</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Ota Käyttöön Erillinen Päivityshakemisto</translation> <translation>Ota Käyttöön Erillinen Päivityshakemisto</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Oletusvälilehti avattaessa asetuksia</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Näytä pelin koko luettelossa</translation> <translation>Näytä pelin koko luettelossa</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafiikka</translation> <translation>Grafiikka</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Rajapinta</translation>
</message>
<message>
<source>User</source>
<translation>Käyttäjä</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Näytönohjain</translation> <translation>Näytönohjain</translation>
@ -801,7 +821,7 @@
<translation>Päivitys:\nRelease: Viralliset versiot, jotka julkaistaan kuukausittain ja saattavat olla hyvin vanhoja, mutta ovat luotettavampia ja testatumpia.\nNightly: Kehitysversiot, joissa on kaikki uusimmat ominaisuudet ja korjaukset, mutta ne saattavat sisältää virheitä ja ovat vähemmän vakaita.</translation> <translation>Päivitys:\nRelease: Viralliset versiot, jotka julkaistaan kuukausittain ja saattavat olla hyvin vanhoja, mutta ovat luotettavampia ja testatumpia.\nNightly: Kehitysversiot, joissa on kaikki uusimmat ominaisuudet ja korjaukset, mutta ne saattavat sisältää virheitä ja ovat vähemmän vakaita.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Soita Otsikkomusiikkia:\nJos peli tukee sitä, ota käyttöön erityisen musiikin soittaminen pelin valinnan yhteydessä käyttöliittymässä.</translation> <translation>Soita Otsikkomusiikkia:\nJos peli tukee sitä, ota käyttöön erityisen musiikin soittaminen pelin valinnan yhteydessä käyttöliittymässä.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Jeux récents</translation> <translation>Jeux récents</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Ouvrir le dossier de shadPS4</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Fermer</translation> <translation>Fermer</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Plein écran</translation> <translation>Plein écran</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Mode Plein Écran</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Dossier séparé pour les mises à jours</translation> <translation>Dossier séparé pour les mises à jours</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Onglet par défaut lors de l'ouverture des paramètres</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Afficher la taille du jeu dans la liste</translation> <translation>Afficher la taille du jeu dans la liste</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphismes</translation> <translation>Graphismes</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interface</translation>
</message>
<message>
<source>User</source>
<translation>Utilisateur</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Carte graphique</translation> <translation>Carte graphique</translation>
@ -801,7 +821,7 @@
<translation>Mise à jour:\nRelease: versions officielles publiées chaque mois qui peuvent être très anciennes, mais plus fiables et testées.\nNightly: versions de développement avec toutes les dernières fonctionnalités et correctifs, mais pouvant avoir des bogues et être moins stables.</translation> <translation>Mise à jour:\nRelease: versions officielles publiées chaque mois qui peuvent être très anciennes, mais plus fiables et testées.\nNightly: versions de développement avec toutes les dernières fonctionnalités et correctifs, mais pouvant avoir des bogues et être moins stables.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Jouer de la musique de titre:\nSi le jeu le prend en charge, cela active la musique spéciale lorsque vous sélectionnez le jeu dans l'interface utilisateur.</translation> <translation>Jouer de la musique de titre:\nSi le jeu le prend en charge, cela active la musique spéciale lorsque vous sélectionnez le jeu dans l'interface utilisateur.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Legutóbbi Játékok</translation> <translation>Legutóbbi Játékok</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Kilépés</translation> <translation>Kilépés</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Teljes Képernyő Engedélyezése</translation> <translation>Teljes Képernyő Engedélyezése</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Teljes képernyős mód</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Külön Frissítési Mappa Engedélyezése</translation> <translation>Külön Frissítési Mappa Engedélyezése</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Alapértelmezett fül a beállítások megnyitásakor</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Játékméret megjelenítése a listában</translation> <translation>Játékméret megjelenítése a listában</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafika</translation> <translation>Grafika</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Felület</translation>
</message>
<message>
<source>User</source>
<translation>Felhasználó</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Grafikai Eszköz</translation> <translation>Grafikai Eszköz</translation>
@ -801,7 +821,7 @@
<translation>Frissítés:\nRelease: Hivatalos verziók, amelyeket havonta adnak ki, és amelyek nagyon elavultak lehetnek, de megbízhatóbbak és teszteltek.\nNightly: Fejlesztési verziók, amelyek az összes legújabb funkciót és javítást tartalmazzák, de hibákat tartalmazhatnak és kevésbé stabilak.</translation> <translation>Frissítés:\nRelease: Hivatalos verziók, amelyeket havonta adnak ki, és amelyek nagyon elavultak lehetnek, de megbízhatóbbak és teszteltek.\nNightly: Fejlesztési verziók, amelyek az összes legújabb funkciót és javítást tartalmazzák, de hibákat tartalmazhatnak és kevésbé stabilak.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>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.</translation> <translation>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.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Mode Layar Penuh</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Tab default saat membuka pengaturan</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Tampilkan Ukuran Game di Daftar</translation> <translation>Tampilkan Ukuran Game di Daftar</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Antarmuka</translation>
</message>
<message>
<source>User</source>
<translation>Pengguna</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Pembaruan:\nRelease: Versi resmi yang dirilis setiap bulan yang mungkin sangat ketinggalan zaman, tetapi lebih dapat diandalkan dan teruji.\nNightly: Versi pengembangan yang memiliki semua fitur dan perbaikan terbaru, tetapi mungkin mengandung bug dan kurang stabil.</translation> <translation>Pembaruan:\nRelease: Versi resmi yang dirilis setiap bulan yang mungkin sangat ketinggalan zaman, tetapi lebih dapat diandalkan dan teruji.\nNightly: Versi pengembangan yang memiliki semua fitur dan perbaikan terbaru, tetapi mungkin mengandung bug dan kurang stabil.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Putar Musik Judul Permainan:\nJika permainan mendukungnya, aktifkan pemutaran musik khusus saat memilih permainan di GUI.</translation> <translation>Putar Musik Judul Permainan:\nJika permainan mendukungnya, aktifkan pemutaran musik khusus saat memilih permainan di GUI.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Giochi Recenti</translation> <translation>Giochi Recenti</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Uscita</translation> <translation>Uscita</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Abilita Schermo Intero</translation> <translation>Abilita Schermo Intero</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Modalità Schermo Intero</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Abilita Cartella Aggiornamenti Separata</translation> <translation>Abilita Cartella Aggiornamenti Separata</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Scheda predefinita all'apertura delle impostazioni</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Mostra la dimensione del gioco nell'elenco</translation> <translation>Mostra la dimensione del gioco nell'elenco</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafica</translation> <translation>Grafica</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interfaccia</translation>
</message>
<message>
<source>User</source>
<translation>Utente</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Scheda Grafica</translation> <translation>Scheda Grafica</translation>
@ -801,7 +821,7 @@
<translation>Aggiornamento:\nRelease: Versioni ufficiali rilasciate ogni mese che potrebbero essere molto datate, ma sono più affidabili e testate.\nNightly: Versioni di sviluppo che hanno tutte le ultime funzionalità e correzioni, ma potrebbero contenere bug e sono meno stabili.</translation> <translation>Aggiornamento:\nRelease: Versioni ufficiali rilasciate ogni mese che potrebbero essere molto datate, ma sono più affidabili e testate.\nNightly: Versioni di sviluppo che hanno tutte le ultime funzionalità e correzioni, ma potrebbero contenere bug e sono meno stabili.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Riproduci Musica del Titolo:\nSe un gioco lo supporta, attiva la riproduzione di musica speciale quando selezioni il gioco nell'interfaccia grafica.</translation> <translation>Riproduci Musica del Titolo:\nSe un gioco lo supporta, attiva la riproduzione di musica speciale quando selezioni il gioco nell'interfaccia grafica.</translation>
</message> </message>
<message> <message>

View File

@ -19,7 +19,7 @@
</message> </message>
<message> <message>
<source>This software should not be used to play games you have not legally obtained.</source> <source>This software should not be used to play games you have not legally obtained.</source>
<translation>使</translation> <translation>使</translation>
</message> </message>
</context> </context>
<context> <context>
@ -33,7 +33,7 @@
<name>GameInfoClass</name> <name>GameInfoClass</name>
<message> <message>
<source>Loading game list, please wait :3</source> <source>Loading game list, please wait :3</source>
<translation>お待ちください :3</translation> <translation>しばらくお待ちください :3</translation>
</message> </message>
<message> <message>
<source>Cancel</source> <source>Cancel</source>
@ -52,7 +52,7 @@
</message> </message>
<message> <message>
<source>Select which directory you want to install to.</source> <source>Select which directory you want to install to.</source>
<translation>Select which directory you want to install to.</translation> <translation></translation>
</message> </message>
</context> </context>
<context> <context>
@ -75,7 +75,7 @@
</message> </message>
<message> <message>
<source>The value for location to install games is not valid.</source> <source>The value for location to install games is not valid.</source>
<translation></translation> <translation></translation>
</message> </message>
</context> </context>
<context> <context>
@ -130,35 +130,35 @@
</message> </message>
<message> <message>
<source>Delete...</source> <source>Delete...</source>
<translation>Delete...</translation> <translation>...</translation>
</message> </message>
<message> <message>
<source>Delete Game</source> <source>Delete Game</source>
<translation>Delete Game</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Delete Update</source> <source>Delete Update</source>
<translation>Delete Update</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Delete DLC</source> <source>Delete DLC</source>
<translation>Delete DLC</translation> <translation>DLCを削除</translation>
</message> </message>
<message> <message>
<source>Compatibility...</source> <source>Compatibility...</source>
<translation>Compatibility...</translation> <translation>...</translation>
</message> </message>
<message> <message>
<source>Update database</source> <source>Update database</source>
<translation>Update database</translation> <translation></translation>
</message> </message>
<message> <message>
<source>View report</source> <source>View report</source>
<translation>View report</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Submit a report</source> <source>Submit a report</source>
<translation>Submit a report</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Shortcut creation</source> <source>Shortcut creation</source>
@ -182,23 +182,23 @@
</message> </message>
<message> <message>
<source>Game</source> <source>Game</source>
<translation>Game</translation> <translation></translation>
</message> </message>
<message> <message>
<source>requiresEnableSeparateUpdateFolder_MSG</source> <source>requiresEnableSeparateUpdateFolder_MSG</source>
<translation>This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it.</translation> <translation> 'アップデートフォルダの分離を有効化' </translation>
</message> </message>
<message> <message>
<source>This game has no update to delete!</source> <source>This game has no update to delete!</source>
<translation>This game has no update to delete!</translation> <translation>!</translation>
</message> </message>
<message> <message>
<source>Update</source> <source>Update</source>
<translation>Update</translation> <translation></translation>
</message> </message>
<message> <message>
<source>This game has no DLC to delete!</source> <source>This game has no DLC to delete!</source>
<translation>This game has no DLC to delete!</translation> <translation>DLCがないため削除することができません!</translation>
</message> </message>
<message> <message>
<source>DLC</source> <source>DLC</source>
@ -206,11 +206,11 @@
</message> </message>
<message> <message>
<source>Delete %1</source> <source>Delete %1</source>
<translation>Delete %1</translation> <translation>%1 </translation>
</message> </message>
<message> <message>
<source>Are you sure you want to delete %1's %2 directory?</source> <source>Are you sure you want to delete %1's %2 directory?</source>
<translation>Are you sure you want to delete %1's %2 directory?</translation> <translation>%1 %2 ?</translation>
</message> </message>
</context> </context>
<context> <context>
@ -241,11 +241,15 @@
</message> </message>
<message> <message>
<source>Install application from a .pkg file</source> <source>Install application from a .pkg file</source>
<translation>.pkgファイルからアプリケーションをインストールする</translation> <translation>.pkgファイルからアプリケーションをインストール</translation>
</message> </message>
<message> <message>
<source>Recent Games</source> <source>Recent Games</source>
<translation></translation> <translation></translation>
</message>
<message>
<source>Open shadPS4 Folder</source>
<translation>shadPS4フォルダを開く</translation>
</message> </message>
<message> <message>
<source>Exit</source> <source>Exit</source>
@ -269,7 +273,7 @@
</message> </message>
<message> <message>
<source>Tiny</source> <source>Tiny</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Small</source> <source>Small</source>
@ -293,7 +297,7 @@
</message> </message>
<message> <message>
<source>Elf Viewer</source> <source>Elf Viewer</source>
<translation>Elfビュ</translation> <translation>Elfビューア</translation>
</message> </message>
<message> <message>
<source>Game Install Directory</source> <source>Game Install Directory</source>
@ -393,11 +397,11 @@
</message> </message>
<message> <message>
<source>You have downloaded cheats for all the games you have installed.</source> <source>You have downloaded cheats for all the games you have installed.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Patches Downloaded Successfully!</source> <source>Patches Downloaded Successfully!</source>
<translation></translation> <translation>!</translation>
</message> </message>
<message> <message>
<source>All Patches available for all games have been downloaded.</source> <source>All Patches available for all games have been downloaded.</source>
@ -421,11 +425,11 @@
</message> </message>
<message> <message>
<source>Only one file can be selected!</source> <source>Only one file can be selected!</source>
<translation>1</translation> <translation>1!</translation>
</message> </message>
<message> <message>
<source>PKG Extraction</source> <source>PKG Extraction</source>
<translation>PKG抽出</translation> <translation>PKG抽出</translation>
</message> </message>
<message> <message>
<source>Patch detected!</source> <source>Patch detected!</source>
@ -469,7 +473,7 @@
</message> </message>
<message> <message>
<source>PKG is a patch, please install the game first!</source> <source>PKG is a patch, please install the game first!</source>
<translation>PKGはパッチです</translation> <translation>PKGはパッチです!</translation>
</message> </message>
<message> <message>
<source>PKG ERROR</source> <source>PKG ERROR</source>
@ -522,11 +526,11 @@
</message> </message>
<message> <message>
<source>Console Language</source> <source>Console Language</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Emulator Language</source> <source>Emulator Language</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Emulator</source> <source>Emulator</source>
@ -536,9 +540,17 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation></translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation></translation>
</message>
<message>
<source>Default tab when opening settings</source>
<translation></translation>
</message> </message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
@ -546,7 +558,7 @@
</message> </message>
<message> <message>
<source>Show Splash</source> <source>Show Splash</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Is PS4 Pro</source> <source>Is PS4 Pro</source>
@ -562,11 +574,11 @@
</message> </message>
<message> <message>
<source>Trophy Key</source> <source>Trophy Key</source>
<translation>Trophy Key</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Trophy</source> <source>Trophy</source>
<translation>Trophy</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Logger</source> <source>Logger</source>
@ -598,7 +610,7 @@
</message> </message>
<message> <message>
<source>Hide Cursor Idle Timeout</source> <source>Hide Cursor Idle Timeout</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>s</source> <source>s</source>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation></translation> <translation></translation>
</message> </message>
<message>
<source>Gui</source>
<translation></translation>
</message>
<message>
<source>User</source>
<translation></translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation></translation> <translation></translation>
@ -702,7 +722,7 @@
</message> </message>
<message> <message>
<source>Disable Trophy Pop-ups</source> <source>Disable Trophy Pop-ups</source>
<translation>Disable Trophy Pop-ups</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Play title music</source> <source>Play title music</source>
@ -710,19 +730,19 @@
</message> </message>
<message> <message>
<source>Update Compatibility Database On Startup</source> <source>Update Compatibility Database On Startup</source>
<translation>Update Compatibility Database On Startup</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Game Compatibility</source> <source>Game Compatibility</source>
<translation>Game Compatibility</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Display Compatibility Data</source> <source>Display Compatibility Data</source>
<translation>Display Compatibility Data</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Update Compatibility Database</source> <source>Update Compatibility Database</source>
<translation>Update Compatibility Database</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Volume</source> <source>Volume</source>
@ -730,7 +750,7 @@
</message> </message>
<message> <message>
<source>Audio Backend</source> <source>Audio Backend</source>
<translation>Audio Backend</translation> <translation> </translation>
</message> </message>
<message> <message>
<source>Save</source> <source>Save</source>
@ -750,15 +770,15 @@
</message> </message>
<message> <message>
<source>Point your mouse at an option to display its description.</source> <source>Point your mouse at an option to display its description.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>consoleLanguageGroupBox</source> <source>consoleLanguageGroupBox</source>
<translation>:\nPS4ゲームが使用する言語を設定します\nこれはゲームがサポートする言語に設定することをお勧めしますが</translation> <translation>:\nPS4ゲームが使用する言語を設定します\nゲームでサポートされている言語に設定することをお勧めしますが</translation>
</message> </message>
<message> <message>
<source>emulatorLanguageGroupBox</source> <source>emulatorLanguageGroupBox</source>
<translation>:\nエミュレーターのユーザーインターフェースの言語を設定します</translation> <translation>:\nエミュレーターのユーザーインターフェースの言語を設定します</translation>
</message> </message>
<message> <message>
<source>fullscreenCheckBox</source> <source>fullscreenCheckBox</source>
@ -766,7 +786,7 @@
</message> </message>
<message> <message>
<source>separateUpdatesCheckBox</source> <source>separateUpdatesCheckBox</source>
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation> <translation>Enable Separate Update Folder:\nゲームのアップデートを別のフォルダにインストールすることで</translation>
</message> </message>
<message> <message>
<source>showSplashCheckBox</source> <source>showSplashCheckBox</source>
@ -774,7 +794,7 @@
</message> </message>
<message> <message>
<source>ps4proCheckBox</source> <source>ps4proCheckBox</source>
<translation>PS4 Proです:\nエミュレーターがPS4 PROとして動作するようにし</translation> <translation>PS4 Pro :\nエミュレーターがPS4 PROとして動作するようになりPS4 PROをサポートする一部のゲームで特別な機能が有効化される場合がありま</translation>
</message> </message>
<message> <message>
<source>discordRPCCheckbox</source> <source>discordRPCCheckbox</source>
@ -786,7 +806,7 @@
</message> </message>
<message> <message>
<source>TrophyKey</source> <source>TrophyKey</source>
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation> <translation>:\nトロフィーの復号に使用されるキーです\n16進数のみを受け入れます</translation>
</message> </message>
<message> <message>
<source>logTypeGroupBox</source> <source>logTypeGroupBox</source>
@ -794,27 +814,27 @@
</message> </message>
<message> <message>
<source>logFilter</source> <source>logFilter</source>
<translation>:\n特定の情報のみを印刷するようにログをフィルタリングします\n例: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" レベル: Trace, Debug, Info, Warning, Error, Critical - </translation> <translation>:\n特定の情報のみを印刷するようにログをフィルタリングします\n例: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" \nレベル: Trace, Debug, Info, Warning, Error, Critical - </translation>
</message> </message>
<message> <message>
<source>updaterGroupBox</source> <source>updaterGroupBox</source>
<translation>:\nRelease: 非常に古いかもしれない\nNightly: 最新の機能と修正がすべて含まれていますが</translation> <translation>:\nRelease: 最新の機能を利用できない可能性があります\nNightly: 最新の機能と修正がすべて含まれていますが</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>:\nゲームがそれをサポートしている場合GUIでゲームを選択したときに特別な音楽を再生することを有効にします</translation> <translation>:\nゲームでサポートされている場合にGUIでゲームを選択したときに特別な音楽を再生する機能を有効にします</translation>
</message> </message>
<message> <message>
<source>disableTrophycheckBox</source> <source>disableTrophycheckBox</source>
<translation>Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window).</translation> <translation>:\nゲーム内でのトロフィー通知を無効化します 使()</translation>
</message> </message>
<message> <message>
<source>hideCursorGroupBox</source> <source>hideCursorGroupBox</source>
<translation>:\nカーソルが消えるタイミングを選択してください:\n決して: いつでもマウスが見えます\nアイドル: アイダルの後に消えるまでの時間を設定します\n常に: マウスは決して見えません</translation> <translation>:\nカーソルが消えるタイミングを選択してください:\n無効: 常にカーソルが表示されます\n非アクティブ時: カーソルの非アクティブ期間が指定した時間を超えた場合にカーソルを隠します\n常に: カーソルは常に隠れた状態になります</translation>
</message> </message>
<message> <message>
<source>idleTimeoutGroupBox</source> <source>idleTimeoutGroupBox</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>backButtonBehaviorGroupBox</source> <source>backButtonBehaviorGroupBox</source>
@ -822,23 +842,23 @@
</message> </message>
<message> <message>
<source>enableCompatibilityCheckBox</source> <source>enableCompatibilityCheckBox</source>
<translation>Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information.</translation> <translation>:\nゲームの互換性に関する情報を表として表示します"起動時に互換性データベースを更新する" </translation>
</message> </message>
<message> <message>
<source>checkCompatibilityOnStartupCheckBox</source> <source>checkCompatibilityOnStartupCheckBox</source>
<translation>Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts.</translation> <translation>:\nshadPS4の起動時に自動で互換性データベースを更新します</translation>
</message> </message>
<message> <message>
<source>updateCompatibilityButton</source> <source>updateCompatibilityButton</source>
<translation>Update Compatibility Database:\nImmediately update the compatibility database.</translation> <translation>:\n今すぐ互換性データベースを更新します</translation>
</message> </message>
<message> <message>
<source>Never</source> <source>Never</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Idle</source> <source>Idle</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Always</source> <source>Always</source>
@ -846,11 +866,11 @@
</message> </message>
<message> <message>
<source>Touchpad Left</source> <source>Touchpad Left</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Touchpad Right</source> <source>Touchpad Right</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Touchpad Center</source> <source>Touchpad Center</source>
@ -862,15 +882,15 @@
</message> </message>
<message> <message>
<source>graphicsAdapterGroupBox</source> <source>graphicsAdapterGroupBox</source>
<translation>:\n複数のGPUシステムで使GPUを選択するか\n</translation> <translation>:\nシステムに複数のGPUが搭載されている場合使GPUを選択するか\n</translation>
</message> </message>
<message> <message>
<source>resolutionLayout</source> <source>resolutionLayout</source>
<translation>/:\n起動時にエミュレーターウィンドウのサイズを設定します\nこれはゲーム内の解像度とは異なります</translation> <translation>/:\n起動時にエミュレーターウィンドウのサイズを設定します\nこれはゲーム内の解像度とは異なります</translation>
</message> </message>
<message> <message>
<source>heightDivider</source> <source>heightDivider</source>
<translation>Vblankディバイダー:\nエミュレーターが更新されるフレームレートにこの数を掛けます</translation> <translation>Vblankディバイダー:\nエミュレーターが更新されるフレームレートにこの数を掛けます!</translation>
</message> </message>
<message> <message>
<source>dumpShadersCheckBox</source> <source>dumpShadersCheckBox</source>
@ -913,11 +933,11 @@
<name>CheatsPatches</name> <name>CheatsPatches</name>
<message> <message>
<source>Cheats / Patches for </source> <source>Cheats / Patches for </source>
<translation>Cheats / Patches for </translation> <translation>/</translation>
</message> </message>
<message> <message>
<source>defaultTextEdit_MSG</source> <source>defaultTextEdit_MSG</source>
<translation>/\n使用には注意してください\n\nリポジトリを選択し\nPatches使\n\nチート/\n問題があればチートの作者に報告してください\n\n新しいチートを作成しましたか\nhttps://github.com/shadps4-emu/ps4_cheats を訪問してください。</translation> <translation>/\n使用には注意してください\n\nリポジトリを選択し\nPatches使\n\nチート/\n問題があればチートの作者に報告してください\n\n新しいチートを作成しましたか\nhttps://github.com/shadps4-emu/ps4_cheats を訪問してください。</translation>
</message> </message>
<message> <message>
<source>No Image Available</source> <source>No Image Available</source>
@ -993,7 +1013,7 @@
</message> </message>
<message> <message>
<source>Unable to open files.json for reading.</source> <source>Unable to open files.json for reading.</source>
<translation>files.jsonを読み込み用に開けません</translation> <translation>files.jsonを読み取りのために開く事が出来ませんでした</translation>
</message> </message>
<message> <message>
<source>No patch file found for the current serial.</source> <source>No patch file found for the current serial.</source>
@ -1001,11 +1021,11 @@
</message> </message>
<message> <message>
<source>Unable to open the file for reading.</source> <source>Unable to open the file for reading.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Unable to open the file for writing.</source> <source>Unable to open the file for writing.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>Failed to parse XML: </source> <source>Failed to parse XML: </source>
@ -1025,7 +1045,7 @@
</message> </message>
<message> <message>
<source>The selected source is invalid.</source> <source>The selected source is invalid.</source>
<translation></translation> <translation></translation>
</message> </message>
<message> <message>
<source>File Exists</source> <source>File Exists</source>
@ -1109,7 +1129,7 @@
</message> </message>
<message> <message>
<source>Failed to open files.json for writing</source> <source>Failed to open files.json for writing</source>
<translation>files.jsonを記録用に開けません</translation> <translation>files.jsonを読み取りのために開く事が出来ませんでした</translation>
</message> </message>
<message> <message>
<source>Author: </source> <source>Author: </source>
@ -1121,7 +1141,7 @@
</message> </message>
<message> <message>
<source>Failed to open files.json for reading.</source> <source>Failed to open files.json for reading.</source>
<translation>files.jsonを読み込み用に開けません</translation> <translation>files.jsonを読み取りのために開く事が出来ませんでした</translation>
</message> </message>
<message> <message>
<source>Name:</source> <source>Name:</source>
@ -1176,43 +1196,43 @@
</message> </message>
<message> <message>
<source>Never Played</source> <source>Never Played</source>
<translation>Never Played</translation> <translation></translation>
</message> </message>
<message> <message>
<source>h</source> <source>h</source>
<translation>h</translation> <translation></translation>
</message> </message>
<message> <message>
<source>m</source> <source>m</source>
<translation>m</translation> <translation></translation>
</message> </message>
<message> <message>
<source>s</source> <source>s</source>
<translation>s</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Compatibility is untested</source> <source>Compatibility is untested</source>
<translation>Compatibility is untested</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Game does not initialize properly / crashes the emulator</source> <source>Game does not initialize properly / crashes the emulator</source>
<translation>Game does not initialize properly / crashes the emulator</translation> <translation>/</translation>
</message> </message>
<message> <message>
<source>Game boots, but only displays a blank screen</source> <source>Game boots, but only displays a blank screen</source>
<translation>Game boots, but only displays a blank screen</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Game displays an image but does not go past the menu</source> <source>Game displays an image but does not go past the menu</source>
<translation>Game displays an image but does not go past the menu</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Game has game-breaking glitches or unplayable performance</source> <source>Game has game-breaking glitches or unplayable performance</source>
<translation>Game has game-breaking glitches or unplayable performance</translation> <translation></translation>
</message> </message>
<message> <message>
<source>Game can be completed with playable performance and no major glitches</source> <source>Game can be completed with playable performance and no major glitches</source>
<translation>Game can be completed with playable performance and no major glitches</translation> <translation></translation>
</message> </message>
</context> </context>
<context> <context>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation> </translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation> </translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation> </translation> <translation> </translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation></translation>
</message>
<message>
<source>User</source>
<translation></translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable.</translation> <translation>Update:\nRelease: Official versions released every month that may be very outdated, but are more reliable and tested.\nNightly: Development versions that have all the latest features and fixes, but may contain bugs and are less stable.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</translation> <translation>Play Title Music:\nIf a game supports it, enable playing special music when selecting the game in the GUI.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Viso ekranas</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Numatytoji kortelė atidarius nustatymus</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Rodyti žaidimo dydį sąraše</translation> <translation>Rodyti žaidimo dydį sąraše</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interfeisa</translation>
</message>
<message>
<source>User</source>
<translation>Naudotojas</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Atnaujinti:\nRelease: Oficialios versijos, išleidžiamos kiekvieną mėnesį, kurios gali būti labai pasenusios, tačiau yra patikimos ir išbandytos.\nNightly: Vystymo versijos, kuriose yra visos naujausios funkcijos ir taisymai, tačiau gali turėti klaidų ir būti mažiau stabilios.</translation> <translation>Atnaujinti:\nRelease: Oficialios versijos, išleidžiamos kiekvieną mėnesį, kurios gali būti labai pasenusios, tačiau yra patikimos ir išbandytos.\nNightly: Vystymo versijos, kuriose yra visos naujausios funkcijos ir taisymai, tačiau gali turėti klaidų ir būti mažiau stabilios.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Groti antraščių muziką:\nJei žaidimas tai palaiko, įjungia specialios muzikos grojimą, kai pasirinkite žaidimą GUI.</translation> <translation>Groti antraščių muziką:\nJei žaidimas tai palaiko, įjungia specialios muzikos grojimą, kai pasirinkite žaidimą GUI.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Nylige spill</translation> <translation>Nylige spill</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Avslutt</translation> <translation>Avslutt</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Aktiver fullskjerm</translation> <translation>Aktiver fullskjerm</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Fullskjermmodus</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Aktiver seperat oppdateringsmappe</translation> <translation>Aktiver seperat oppdateringsmappe</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Standardfanen når innstillingene åpnes</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Vis spillstørrelse i listen</translation> <translation>Vis spillstørrelse i listen</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafikk</translation> <translation>Grafikk</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Grensesnitt</translation>
</message>
<message>
<source>User</source>
<translation>Bruker</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Grafikkenhet</translation> <translation>Grafikkenhet</translation>
@ -801,7 +821,7 @@
<translation>Oppdatering:\nRelease: Offisielle versjoner utgitt hver måned som kan være veldig utdaterte, men er mer pålitelige og testet.\nNightly: Utviklingsversjoner som har alle de nyeste funksjonene og feilrettingene, men som kan inneholde feil og er mindre stabile.</translation> <translation>Oppdatering:\nRelease: Offisielle versjoner utgitt hver måned som kan være veldig utdaterte, men er mer pålitelige og testet.\nNightly: Utviklingsversjoner som har alle de nyeste funksjonene og feilrettingene, men som kan inneholde feil og er mindre stabile.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Spille tittelmusikk:\nHvis et spill støtter det, aktiveres det spesiell musikk når du velger spillet i menyen.</translation> <translation>Spille tittelmusikk:\nHvis et spill støtter det, aktiveres det spesiell musikk når du velger spillet i menyen.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Volledig schermmodus</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Standaardtabblad bij het openen van instellingen</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Toon grootte van het spel in de lijst</translation> <translation>Toon grootte van het spel in de lijst</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interface</translation>
</message>
<message>
<source>User</source>
<translation>Gebruiker</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Updateren:\nRelease: Officiële versies die elke maand worden uitgebracht, die zeer verouderd kunnen zijn, maar betrouwbaar en getest zijn.\nNightly: Ontwikkelingsversies die alle nieuwste functies en bugfixes bevatten, maar mogelijk bugs bevatten en minder stabiel zijn.</translation> <translation>Updateren:\nRelease: Officiële versies die elke maand worden uitgebracht, die zeer verouderd kunnen zijn, maar betrouwbaar en getest zijn.\nNightly: Ontwikkelingsversies die alle nieuwste functies en bugfixes bevatten, maar mogelijk bugs bevatten en minder stabiel zijn.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Speel titelsong:\nAls een game dit ondersteunt, wordt speciale muziek afgespeeld wanneer je het spel in de GUI selecteert.</translation> <translation>Speel titelsong:\nAls een game dit ondersteunt, wordt speciale muziek afgespeeld wanneer je het spel in de GUI selecteert.</translation>
</message> </message>
<message> <message>

View File

@ -52,7 +52,7 @@
</message> </message>
<message> <message>
<source>Select which directory you want to install to.</source> <source>Select which directory you want to install to.</source>
<translation>Select which directory you want to install to.</translation> <translation>Wybierz katalog, do którego chcesz zainstalować.</translation>
</message> </message>
</context> </context>
<context> <context>
@ -130,35 +130,35 @@
</message> </message>
<message> <message>
<source>Delete...</source> <source>Delete...</source>
<translation>Delete...</translation> <translation>Usuń...</translation>
</message> </message>
<message> <message>
<source>Delete Game</source> <source>Delete Game</source>
<translation>Delete Game</translation> <translation>Usuń Grę</translation>
</message> </message>
<message> <message>
<source>Delete Update</source> <source>Delete Update</source>
<translation>Delete Update</translation> <translation>Usuń Aktualizację</translation>
</message> </message>
<message> <message>
<source>Delete DLC</source> <source>Delete DLC</source>
<translation>Delete DLC</translation> <translation>Usuń DLC</translation>
</message> </message>
<message> <message>
<source>Compatibility...</source> <source>Compatibility...</source>
<translation>Compatibility...</translation> <translation>kompatybilność...</translation>
</message> </message>
<message> <message>
<source>Update database</source> <source>Update database</source>
<translation>Update database</translation> <translation>Zaktualizuj bazę danych</translation>
</message> </message>
<message> <message>
<source>View report</source> <source>View report</source>
<translation>View report</translation> <translation>Wyświetl zgłoszenie</translation>
</message> </message>
<message> <message>
<source>Submit a report</source> <source>Submit a report</source>
<translation>Submit a report</translation> <translation>Wyślij zgłoszenie</translation>
</message> </message>
<message> <message>
<source>Shortcut creation</source> <source>Shortcut creation</source>
@ -182,23 +182,23 @@
</message> </message>
<message> <message>
<source>Game</source> <source>Game</source>
<translation>Game</translation> <translation>Gra</translation>
</message> </message>
<message> <message>
<source>requiresEnableSeparateUpdateFolder_MSG</source> <source>requiresEnableSeparateUpdateFolder_MSG</source>
<translation>This feature requires the 'Enable Separate Update Folder' config option to work. If you want to use this feature, please enable it.</translation> <translation>Ta funkcja wymaga do działania opcji Włącz oddzielny folder aktualizacji. Jeśli chcesz korzystać z tej funkcji, włącz .</translation>
</message> </message>
<message> <message>
<source>This game has no update to delete!</source> <source>This game has no update to delete!</source>
<translation>This game has no update to delete!</translation> <translation>Ta gra nie ma aktualizacji do usunięcia!</translation>
</message> </message>
<message> <message>
<source>Update</source> <source>Update</source>
<translation>Update</translation> <translation>Aktualizacja</translation>
</message> </message>
<message> <message>
<source>This game has no DLC to delete!</source> <source>This game has no DLC to delete!</source>
<translation>This game has no DLC to delete!</translation> <translation>Ta gra nie ma DLC do usunięcia!</translation>
</message> </message>
<message> <message>
<source>DLC</source> <source>DLC</source>
@ -206,11 +206,11 @@
</message> </message>
<message> <message>
<source>Delete %1</source> <source>Delete %1</source>
<translation>Delete %1</translation> <translation>Usuń %1</translation>
</message> </message>
<message> <message>
<source>Are you sure you want to delete %1's %2 directory?</source> <source>Are you sure you want to delete %1's %2 directory?</source>
<translation>Are you sure you want to delete %1's %2 directory?</translation> <translation>Czy na pewno chcesz usunąć katalog %1 z %2?</translation>
</message> </message>
</context> </context>
<context> <context>
@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Ostatnie gry</translation> <translation>Ostatnie gry</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Otwórz folder shadPS4</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Wyjdź</translation> <translation>Wyjdź</translation>
@ -536,9 +540,17 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Włącz pełny ekran</translation> <translation>Włącz pełny ekran</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Tryb Pełnoekranowy</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Włącz oddzielny folder aktualizacji</translation>
</message>
<message>
<source>Default tab when opening settings</source>
<translation>Domyślna zakładka podczas otwierania ustawień</translation>
</message> </message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
@ -562,11 +574,11 @@
</message> </message>
<message> <message>
<source>Trophy Key</source> <source>Trophy Key</source>
<translation>Trophy Key</translation> <translation>Klucz trofeów</translation>
</message> </message>
<message> <message>
<source>Trophy</source> <source>Trophy</source>
<translation>Trophy</translation> <translation>Trofeum</translation>
</message> </message>
<message> <message>
<source>Logger</source> <source>Logger</source>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafika</translation> <translation>Grafika</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interfejs</translation>
</message>
<message>
<source>User</source>
<translation>Użytkownik</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Karta graficzna</translation> <translation>Karta graficzna</translation>
@ -702,7 +722,7 @@
</message> </message>
<message> <message>
<source>Disable Trophy Pop-ups</source> <source>Disable Trophy Pop-ups</source>
<translation>Disable Trophy Pop-ups</translation> <translation>Wyłącz wyskakujące okienka trofeów</translation>
</message> </message>
<message> <message>
<source>Play title music</source> <source>Play title music</source>
@ -710,19 +730,19 @@
</message> </message>
<message> <message>
<source>Update Compatibility Database On Startup</source> <source>Update Compatibility Database On Startup</source>
<translation>Update Compatibility Database On Startup</translation> <translation>Aktualizuj bazę danych zgodności podczas uruchamiania</translation>
</message> </message>
<message> <message>
<source>Game Compatibility</source> <source>Game Compatibility</source>
<translation>Game Compatibility</translation> <translation>Kompatybilność gier</translation>
</message> </message>
<message> <message>
<source>Display Compatibility Data</source> <source>Display Compatibility Data</source>
<translation>Display Compatibility Data</translation> <translation>Wyświetl dane zgodności</translation>
</message> </message>
<message> <message>
<source>Update Compatibility Database</source> <source>Update Compatibility Database</source>
<translation>Update Compatibility Database</translation> <translation>Aktualizuj bazę danych zgodności</translation>
</message> </message>
<message> <message>
<source>Volume</source> <source>Volume</source>
@ -730,7 +750,7 @@
</message> </message>
<message> <message>
<source>Audio Backend</source> <source>Audio Backend</source>
<translation>Audio Backend</translation> <translation>Zaplecze audio</translation>
</message> </message>
<message> <message>
<source>Save</source> <source>Save</source>
@ -766,7 +786,7 @@
</message> </message>
<message> <message>
<source>separateUpdatesCheckBox</source> <source>separateUpdatesCheckBox</source>
<translation>Enable Separate Update Folder:\nEnables installing game updates into a separate folder for easy management.</translation> <translation>Włącz oddzielny folder aktualizacji:\nUmożliwia instalowanie aktualizacji gier w oddzielnym folderze w celu łatwego zarządzania.</translation>
</message> </message>
<message> <message>
<source>showSplashCheckBox</source> <source>showSplashCheckBox</source>
@ -778,7 +798,7 @@
</message> </message>
<message> <message>
<source>discordRPCCheckbox</source> <source>discordRPCCheckbox</source>
<translation>Włącz Discord Rich Presence:\nWyświetla ikonę emuladora i odpowiednie informacje na twoim profilu Discord.</translation> <translation>Włącz Discord Rich Presence:\nWyświetla ikonę emulatora i odpowiednie informacje na twoim profilu Discord.</translation>
</message> </message>
<message> <message>
<source>userName</source> <source>userName</source>
@ -786,7 +806,7 @@
</message> </message>
<message> <message>
<source>TrophyKey</source> <source>TrophyKey</source>
<translation>Trophy Key:\nKey used to decrypt trophies. Must be obtained from your jailbroken console.\nMust contain only hex characters.</translation> <translation>Klucz trofeów:\nKlucz używany do odszyfrowywania trofeów. Musi być uzyskany z konsoli po jailbreaku. Musi zawierać tylko znaki w kodzie szesnastkowym.</translation>
</message> </message>
<message> <message>
<source>logTypeGroupBox</source> <source>logTypeGroupBox</source>
@ -801,12 +821,12 @@
<translation>Aktualizator:\nRelease: Oficjalne wersje wydawane co miesiąc, które mogą być bardzo przestarzałe, ale niezawodne i przetestowane.\nNightly: Wersje rozwojowe, które zawierają wszystkie najnowsze funkcje i poprawki błędów, ale mogą mieć błędy i być mniej stabilne.</translation> <translation>Aktualizator:\nRelease: Oficjalne wersje wydawane co miesiąc, które mogą być bardzo przestarzałe, ale niezawodne i przetestowane.\nNightly: Wersje rozwojowe, które zawierają wszystkie najnowsze funkcje i poprawki błędów, ale mogą mieć błędy i być mniej stabilne.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Odtwórz muzykę tytułową:\nJeśli gra to obsługuje, aktywuje odtwarzanie specjalnej muzyki podczas wybierania gry w GUI.</translation> <translation>Odtwórz muzykę tytułową:\nJeśli gra to obsługuje, aktywuje odtwarzanie specjalnej muzyki podczas wybierania gry w GUI.</translation>
</message> </message>
<message> <message>
<source>disableTrophycheckBox</source> <source>disableTrophycheckBox</source>
<translation>Disable Trophy Pop-ups:\nDisable in-game trophy notifications. Trophy progress can still be tracked using the Trophy Viewer (right-click the game in the main window).</translation> <translation>Wyłącz wyskakujące okienka trofeów:\nWyłącz powiadomienia o trofeach w grze. Postępy w zdobywaniu trofeów można nadal śledzić za pomocą przeglądarki trofeów (kliknij prawym przyciskiem myszy grę w oknie głównym).</translation>
</message> </message>
<message> <message>
<source>hideCursorGroupBox</source> <source>hideCursorGroupBox</source>
@ -822,15 +842,15 @@
</message> </message>
<message> <message>
<source>enableCompatibilityCheckBox</source> <source>enableCompatibilityCheckBox</source>
<translation>Display Compatibility Data:\nDisplays game compatibility information in table view. Enable "Update Compatibility On Startup" to get up-to-date information.</translation> <translation>Wyświetl dane zgodności:\nWyświetla informacje o kompatybilności gry w widoku tabeli. Włącz opcję Aktualizuj zgodność przy uruchomieniu, aby uzyskać aktualne informacje.</translation>
</message> </message>
<message> <message>
<source>checkCompatibilityOnStartupCheckBox</source> <source>checkCompatibilityOnStartupCheckBox</source>
<translation>Update Compatibility On Startup:\nAutomatically update the compatibility database when shadPS4 starts.</translation> <translation>Aktualizuj zgodność przy uruchomieniu:\nAutomatycznie aktualizuj bazę danych kompatybilności podczas uruchamiania shadPS4.</translation>
</message> </message>
<message> <message>
<source>updateCompatibilityButton</source> <source>updateCompatibilityButton</source>
<translation>Update Compatibility Database:\nImmediately update the compatibility database.</translation> <translation>Zaktualizuj bazę danych zgodności:\nNatychmiast zaktualizuj bazę danych zgodności.</translation>
</message> </message>
<message> <message>
<source>Never</source> <source>Never</source>
@ -913,7 +933,7 @@
<name>CheatsPatches</name> <name>CheatsPatches</name>
<message> <message>
<source>Cheats / Patches for </source> <source>Cheats / Patches for </source>
<translation>Cheats / Patches for </translation> <translation>Kody / Łatki dla </translation>
</message> </message>
<message> <message>
<source>defaultTextEdit_MSG</source> <source>defaultTextEdit_MSG</source>
@ -1125,7 +1145,7 @@
</message> </message>
<message> <message>
<source>Failed to parse JSON:</source> <source>Failed to parse JSON:</source>
<translation>Nie udało się przeanlizować JSON:</translation> <translation>Nie udało się przeanalizować JSON:</translation>
</message> </message>
<message> <message>
<source>Can't apply cheats before the game is started</source> <source>Can't apply cheats before the game is started</source>
@ -1148,7 +1168,7 @@
</message> </message>
<message> <message>
<source>Compatibility</source> <source>Compatibility</source>
<translation>Compatibility</translation> <translation>Zgodność</translation>
</message> </message>
<message> <message>
<source>Region</source> <source>Region</source>
@ -1176,7 +1196,7 @@
</message> </message>
<message> <message>
<source>Never Played</source> <source>Never Played</source>
<translation>Never Played</translation> <translation>Nigdy nie grane</translation>
</message> </message>
<message> <message>
<source>h</source> <source>h</source>
@ -1192,27 +1212,27 @@
</message> </message>
<message> <message>
<source>Compatibility is untested</source> <source>Compatibility is untested</source>
<translation>Compatibility is untested</translation> <translation>Kompatybilność nie została przetestowana</translation>
</message> </message>
<message> <message>
<source>Game does not initialize properly / crashes the emulator</source> <source>Game does not initialize properly / crashes the emulator</source>
<translation>Game does not initialize properly / crashes the emulator</translation> <translation>Gra nie inicjuje się poprawnie / zawiesza się emulator</translation>
</message> </message>
<message> <message>
<source>Game boots, but only displays a blank screen</source> <source>Game boots, but only displays a blank screen</source>
<translation>Game boots, but only displays a blank screen</translation> <translation>Gra uruchamia się, ale wyświetla tylko pusty ekran</translation>
</message> </message>
<message> <message>
<source>Game displays an image but does not go past the menu</source> <source>Game displays an image but does not go past the menu</source>
<translation>Game displays an image but does not go past the menu</translation> <translation>Gra wyświetla obraz, ale nie przechodzi do menu</translation>
</message> </message>
<message> <message>
<source>Game has game-breaking glitches or unplayable performance</source> <source>Game has game-breaking glitches or unplayable performance</source>
<translation>Game has game-breaking glitches or unplayable performance</translation> <translation>Gra ma usterki przerywające rozgrywkę lub niegrywalną wydajność</translation>
</message> </message>
<message> <message>
<source>Game can be completed with playable performance and no major glitches</source> <source>Game can be completed with playable performance and no major glitches</source>
<translation>Game can be completed with playable performance and no major glitches</translation> <translation>Gmożna ukończyć z grywalną wydajnością i bez większych usterek</translation>
</message> </message>
</context> </context>
<context> <context>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Jogos Recentes</translation> <translation>Jogos Recentes</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Abrir pasta shadPS4</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Sair</translation> <translation>Sair</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Ativar Tela Cheia</translation> <translation>Ativar Tela Cheia</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Modo de Tela Cheia</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Habilitar pasta de atualização separada</translation> <translation>Habilitar pasta de atualização separada</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Aba padrão ao abrir as configurações</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Mostrar Tamanho do Jogo na Lista</translation> <translation>Mostrar Tamanho do Jogo na Lista</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Gráficos</translation> <translation>Gráficos</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interface</translation>
</message>
<message>
<source>User</source>
<translation>Usuário</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Placa de Vídeo</translation> <translation>Placa de Vídeo</translation>
@ -762,7 +782,7 @@
</message> </message>
<message> <message>
<source>fullscreenCheckBox</source> <source>fullscreenCheckBox</source>
<translation>Ativar Tela Cheia:\nMove automaticamente a janela do jogo para o modo tela cheia.\nIsso pode ser alterado pressionando a tecla F11.</translation> <translation>Ativar Tela Cheia:\nAltera a janela do jogo para o modo tela cheia.\nIsso pode ser alterado pressionando a tecla F11.</translation>
</message> </message>
<message> <message>
<source>separateUpdatesCheckBox</source> <source>separateUpdatesCheckBox</source>
@ -801,7 +821,11 @@
<translation>Atualizações:\nRelease: Versões oficiais que são lançadas todo mês e podem ser bastante antigas, mas são mais confiáveis e testadas.\nNightly: Versões de desenvolvimento que têm todos os novos recursos e correções, mas podem ter bugs e ser instáveis.</translation> <translation>Atualizações:\nRelease: Versões oficiais que são lançadas todo mês e podem ser bastante antigas, mas são mais confiáveis e testadas.\nNightly: Versões de desenvolvimento que têm todos os novos recursos e correções, mas podem ter bugs e ser instáveis.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>chooseHomeTabGroupBox</source>
<translation>do menu.</translation>
</message>
<message>
<source>GUIMusicGroupBox</source>
<translation>Reproduzir música de abertura:\nSe o jogo suportar, ativa a reprodução de uma música especial ao selecionar o jogo na interface do menu.</translation> <translation>Reproduzir música de abertura:\nSe o jogo suportar, ativa a reprodução de uma música especial ao selecionar o jogo na interface do menu.</translation>
</message> </message>
<message> <message>
@ -1341,4 +1365,4 @@
<translation>TB</translation> <translation>TB</translation>
</message> </message>
</context> </context>
</TS> </TS>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Recent Games</translation> <translation>Recent Games</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Exit</translation> <translation>Exit</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Enable Fullscreen</translation> <translation>Enable Fullscreen</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Mod Ecran Complet</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Enable Separate Update Folder</translation> <translation>Enable Separate Update Folder</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Tab-ul implicit la deschiderea setărilor</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Afișează dimensiunea jocului în listă</translation> <translation>Afișează dimensiunea jocului în listă</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Graphics</translation> <translation>Graphics</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Interfață</translation>
</message>
<message>
<source>User</source>
<translation>Utilizator</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Graphics Device</translation> <translation>Graphics Device</translation>
@ -801,7 +821,7 @@
<translation>Actualizare:\nRelease: Versiuni oficiale lansate în fiecare lună, care pot fi foarte învechite, dar sunt mai fiabile și testate.\nNightly: Versiuni de dezvoltare care conțin toate cele mai recente funcții și corecții, dar pot conține erori și sunt mai puțin stabile.</translation> <translation>Actualizare:\nRelease: Versiuni oficiale lansate în fiecare lună, care pot fi foarte învechite, dar sunt mai fiabile și testate.\nNightly: Versiuni de dezvoltare care conțin toate cele mai recente funcții și corecții, dar pot conține erori și sunt mai puțin stabile.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Redă muzica titlului:\nDacă un joc o suportă, activează redarea muzicii speciale când selectezi jocul în GUI.</translation> <translation>Redă muzica titlului:\nDacă un joc o suportă, activează redarea muzicii speciale când selectezi jocul în GUI.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Недавние игры</translation> <translation>Недавние игры</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Выход</translation> <translation>Выход</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Полноэкранный режим</translation> <translation>Полноэкранный режим</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Режим Полного Экран</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Отдельная папка обновлений</translation> <translation>Отдельная папка обновлений</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Вкладка по умолчанию при открытии настроек</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Показать размер игры в списке</translation> <translation>Показать размер игры в списке</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Графика</translation> <translation>Графика</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Интерфейс</translation>
</message>
<message>
<source>User</source>
<translation>Пользователь</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Графическое устройство</translation> <translation>Графическое устройство</translation>
@ -801,7 +821,7 @@
<translation>Обновление:\nRelease: Официальные версии, которые выпускаются каждый месяц и могут быть очень старыми, но они более надежные и проверенные.\nNightly: Версии разработки, которые содержат все последние функции и исправления, но могут содержать ошибки и менее стабильны.</translation> <translation>Обновление:\nRelease: Официальные версии, которые выпускаются каждый месяц и могут быть очень старыми, но они более надежные и проверенные.\nNightly: Версии разработки, которые содержат все последние функции и исправления, но могут содержать ошибки и менее стабильны.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Играть заглавную музыку:\nВключает воспроизведение специальной музыки при выборе игры в списке, если она это поддерживает.</translation> <translation>Играть заглавную музыку:\nВключает воспроизведение специальной музыки при выборе игры в списке, если она это поддерживает.</translation>
</message> </message>
<message> <message>

View File

@ -247,6 +247,10 @@
<source>Recent Games</source> <source>Recent Games</source>
<translation>Lojërat e fundit</translation> <translation>Lojërat e fundit</translation>
</message> </message>
<message>
<source>Open shadPS4 Folder</source>
<translation>Open shadPS4 Folder</translation>
</message>
<message> <message>
<source>Exit</source> <source>Exit</source>
<translation>Dil</translation> <translation>Dil</translation>
@ -536,10 +540,18 @@
<source>Enable Fullscreen</source> <source>Enable Fullscreen</source>
<translation>Aktivizo Ekranin e plotë</translation> <translation>Aktivizo Ekranin e plotë</translation>
</message> </message>
<message>
<source>Fullscreen Mode</source>
<translation>Modaliteti i Plotë</translation>
</message>
<message> <message>
<source>Enable Separate Update Folder</source> <source>Enable Separate Update Folder</source>
<translation>Aktivizo dosjen e ndarë përditësimit</translation> <translation>Aktivizo dosjen e ndarë përditësimit</translation>
</message> </message>
<message>
<source>Default tab when opening settings</source>
<translation>Skeda e parazgjedhur kur hapni cilësimet</translation>
</message>
<message> <message>
<source>Show Game Size In List</source> <source>Show Game Size In List</source>
<translation>Shfaq madhësinë e lojës listë</translation> <translation>Shfaq madhësinë e lojës listë</translation>
@ -616,6 +628,14 @@
<source>Graphics</source> <source>Graphics</source>
<translation>Grafika</translation> <translation>Grafika</translation>
</message> </message>
<message>
<source>Gui</source>
<translation>Ndërfaqe</translation>
</message>
<message>
<source>User</source>
<translation>Përdorues</translation>
</message>
<message> <message>
<source>Graphics Device</source> <source>Graphics Device</source>
<translation>Pajisja e Grafikës</translation> <translation>Pajisja e Grafikës</translation>
@ -801,7 +821,7 @@
<translation>Përditësimi:\nRelease: Versionet zyrtare lëshuara çdo muaj mund jenë shumë vjetra, por janë besueshme dhe provuara.\nNightly: Versionet e zhvillimit kanë gjitha veçoritë dhe rregullimet fundit, por mund përmbajnë gabime dhe janë pak qëndrueshme.</translation> <translation>Përditësimi:\nRelease: Versionet zyrtare lëshuara çdo muaj mund jenë shumë vjetra, por janë besueshme dhe provuara.\nNightly: Versionet e zhvillimit kanë gjitha veçoritë dhe rregullimet fundit, por mund përmbajnë gabime dhe janë pak qëndrueshme.</translation>
</message> </message>
<message> <message>
<source>GUIgroupBox</source> <source>GUIMusicGroupBox</source>
<translation>Luaj muzikën e titullit:\nNëse një lojë e mbështet, aktivizohet luajtja e muzikës veçantë kur zgjidhësh lojën GUI.</translation> <translation>Luaj muzikën e titullit:\nNëse një lojë e mbështet, aktivizohet luajtja e muzikës veçantë kur zgjidhësh lojën GUI.</translation>
</message> </message>
<message> <message>

Some files were not shown because too many files have changed in this diff Show More