Merge remote-tracking branch 'origin/main' into feature/fullscreen-flag

This commit is contained in:
Robyn Dressler 2024-10-08 20:12:18 -05:00
commit c51307377f
79 changed files with 783 additions and 424 deletions

3
.gitmodules vendored
View File

@ -95,3 +95,6 @@
path = externals/pugixml path = externals/pugixml
url = https://github.com/zeux/pugixml.git url = https://github.com/zeux/pugixml.git
shallow = true shallow = true
[submodule "externals/discord-rpc"]
path = externals/discord-rpc
url = https://github.com/shadps4-emu/ext-discord-rpc

View File

@ -374,6 +374,8 @@ set(COMMON src/common/logging/backend.cpp
src/common/debug.h src/common/debug.h
src/common/decoder.cpp src/common/decoder.cpp
src/common/decoder.h src/common/decoder.h
src/common/discord_rpc_handler.cpp
src/common/discord_rpc_handler.h
src/common/elf_info.h src/common/elf_info.h
src/common/endian.h src/common/endian.h
src/common/enum.h src/common/enum.h
@ -858,3 +860,6 @@ if (UNIX AND NOT APPLE)
target_link_libraries(shadps4 PRIVATE ${OPENSSL_LIBRARIES}) target_link_libraries(shadps4 PRIVATE ${OPENSSL_LIBRARIES})
endif() endif()
endif() endif()
# Discord RPC
target_link_libraries(shadps4 PRIVATE discord-rpc)

View File

@ -102,7 +102,7 @@ PAD DOWN | DOWN |
PAD LEFT | LEFT | PAD LEFT | LEFT |
PAD RIGHT | RIGHT | PAD RIGHT | RIGHT |
OPTIONS | RETURN | OPTIONS | RETURN |
TOUCH PAD | SPACE | BACK BUTTON / TOUCH PAD | SPACE |
L1 | Q | L1 | Q |
R1 | U | R1 | U |
L2 | E | L2 | E |

View File

@ -184,5 +184,10 @@ if (NOT TARGET pugixml::pugixml)
add_subdirectory(pugixml) add_subdirectory(pugixml)
endif() endif()
# Discord RPC
set(BUILD_EXAMPLES OFF)
add_subdirectory(discord-rpc/)
target_include_directories(discord-rpc INTERFACE discord-rpc/include)
# GCN Headers # GCN Headers
add_subdirectory(gcn) add_subdirectory(gcn)

2
externals/date vendored

@ -1 +1 @@
Subproject commit 51ce7e131079c061533d741be5fe7cca57f2faac Subproject commit dd8affc6de5755e07638bf0a14382d29549d6ee9

1
externals/discord-rpc vendored Submodule

@ -0,0 +1 @@
Subproject commit 4ec218155d73bcb8022f8f7ca72305d801f84beb

2
externals/sdl3 vendored

@ -1 +1 @@
Subproject commit 0548050fc5a4edf1f47c3633c2cd06d8762b5532 Subproject commit 54e622c2e6af456bfef382fae44c17682d5ac88a

2
externals/sirit vendored

@ -1 +1 @@
Subproject commit 37090c74cc6e680f2bc334cac8fd182f7634a1f6 Subproject commit 6cecb95d679c82c413d1f989e0b7ad9af130600d

View File

@ -103,7 +103,7 @@ s32 SDLAudio::AudioOutOutput(s32 handle, const void* ptr) {
const size_t data_size = port.samples_num * port.sample_size * port.channels_num; const size_t data_size = port.samples_num * port.sample_size * port.channels_num;
SDL_bool result = SDL_PutAudioStreamData(port.stream, ptr, data_size); bool result = SDL_PutAudioStreamData(port.stream, ptr, data_size);
lock.unlock(); // Unlock only after necessary operations lock.unlock(); // Unlock only after necessary operations

View File

@ -34,6 +34,7 @@ static bool isNeo = false;
static bool isFullscreen = false; static bool isFullscreen = false;
static bool playBGM = false; static bool playBGM = false;
static int BGMvolume = 50; static int BGMvolume = 50;
static bool enableDiscordRPC = false;
static u32 screenWidth = 1280; static u32 screenWidth = 1280;
static u32 screenHeight = 720; static u32 screenHeight = 720;
static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select static s32 gpuId = -1; // Vulkan physical device index. Set to negative for auto select
@ -42,6 +43,7 @@ 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 patchFile = ""; static std::string patchFile = "";
static std::string backButtonBehavior = "left";
static bool useSpecialPad = false; static bool useSpecialPad = false;
static int specialPadClass = 1; static int specialPadClass = 1;
static bool isDebugDump = false; static bool isDebugDump = false;
@ -57,6 +59,8 @@ static bool vkValidationGpu = false;
static bool rdocEnable = false; static bool rdocEnable = false;
static bool vkMarkers = false; static bool vkMarkers = false;
static bool vkCrashDiagnostic = false; static bool vkCrashDiagnostic = false;
static s16 cursorState = HideCursorState::Idle;
static int cursorHideTimeout = 5; // 5 seconds (default)
// Gui // Gui
std::filesystem::path settings_install_dir = {}; std::filesystem::path settings_install_dir = {};
@ -96,6 +100,18 @@ int getBGMvolume() {
return BGMvolume; return BGMvolume;
} }
bool getEnableDiscordRPC() {
return enableDiscordRPC;
}
s16 getCursorState() {
return cursorState;
}
int getCursorHideTimeout() {
return cursorHideTimeout;
}
u32 getScreenWidth() { u32 getScreenWidth() {
return screenWidth; return screenWidth;
} }
@ -128,6 +144,10 @@ std::string getPatchFile() {
return patchFile; return patchFile;
} }
std::string getBackButtonBehavior() {
return backButtonBehavior;
}
bool getUseSpecialPad() { bool getUseSpecialPad() {
return useSpecialPad; return useSpecialPad;
} }
@ -256,6 +276,18 @@ void setBGMvolume(int volume) {
BGMvolume = volume; BGMvolume = volume;
} }
void setEnableDiscordRPC(bool enable) {
enableDiscordRPC = enable;
}
void setCursorState(s16 newCursorState) {
cursorState = newCursorState;
}
void setCursorHideTimeout(int newcursorHideTimeout) {
cursorHideTimeout = newcursorHideTimeout;
}
void setLanguage(u32 language) { void setLanguage(u32 language) {
m_language = language; m_language = language;
} }
@ -284,6 +316,10 @@ void setPatchFile(const std::string& fileName) {
patchFile = fileName; patchFile = fileName;
} }
void setBackButtonBehavior(const std::string& type) {
backButtonBehavior = type;
}
void setUseSpecialPad(bool use) { void setUseSpecialPad(bool use) {
useSpecialPad = use; useSpecialPad = use;
} }
@ -434,6 +470,7 @@ void load(const std::filesystem::path& path) {
isFullscreen = toml::find_or<bool>(general, "Fullscreen", false); isFullscreen = toml::find_or<bool>(general, "Fullscreen", false);
playBGM = toml::find_or<bool>(general, "playBGM", false); playBGM = toml::find_or<bool>(general, "playBGM", false);
BGMvolume = toml::find_or<int>(general, "BGMvolume", 50); BGMvolume = toml::find_or<int>(general, "BGMvolume", 50);
enableDiscordRPC = toml::find_or<bool>(general, "enableDiscordRPC", true);
logFilter = toml::find_or<std::string>(general, "logFilter", ""); logFilter = toml::find_or<std::string>(general, "logFilter", "");
logType = toml::find_or<std::string>(general, "logType", "sync"); logType = toml::find_or<std::string>(general, "logType", "sync");
userName = toml::find_or<std::string>(general, "userName", "shadPS4"); userName = toml::find_or<std::string>(general, "userName", "shadPS4");
@ -445,11 +482,14 @@ void load(const std::filesystem::path& path) {
isShowSplash = toml::find_or<bool>(general, "showSplash", true); isShowSplash = toml::find_or<bool>(general, "showSplash", true);
isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false); isAutoUpdate = toml::find_or<bool>(general, "autoUpdate", false);
patchFile = toml::find_or<std::string>(general, "patchFile", ""); patchFile = toml::find_or<std::string>(general, "patchFile", "");
backButtonBehavior = toml::find_or<std::string>(general, "backButtonBehavior", "left");
} }
if (data.contains("Input")) { if (data.contains("Input")) {
const toml::value& input = data.at("Input"); const toml::value& input = data.at("Input");
cursorState = toml::find_or<int>(input, "cursorState", HideCursorState::Idle);
cursorHideTimeout = toml::find_or<int>(input, "cursorHideTimeout", 5);
useSpecialPad = toml::find_or<bool>(input, "useSpecialPad", false); useSpecialPad = toml::find_or<bool>(input, "useSpecialPad", false);
specialPadClass = toml::find_or<int>(input, "specialPadClass", 1); specialPadClass = toml::find_or<int>(input, "specialPadClass", 1);
} }
@ -549,6 +589,7 @@ void save(const std::filesystem::path& path) {
data["General"]["Fullscreen"] = isFullscreen; data["General"]["Fullscreen"] = isFullscreen;
data["General"]["playBGM"] = playBGM; data["General"]["playBGM"] = playBGM;
data["General"]["BGMvolume"] = BGMvolume; data["General"]["BGMvolume"] = BGMvolume;
data["General"]["enableDiscordRPC"] = enableDiscordRPC;
data["General"]["logFilter"] = logFilter; data["General"]["logFilter"] = logFilter;
data["General"]["logType"] = logType; data["General"]["logType"] = logType;
data["General"]["userName"] = userName; data["General"]["userName"] = userName;
@ -556,6 +597,9 @@ void save(const std::filesystem::path& path) {
data["General"]["showSplash"] = isShowSplash; data["General"]["showSplash"] = isShowSplash;
data["General"]["autoUpdate"] = isAutoUpdate; data["General"]["autoUpdate"] = isAutoUpdate;
data["General"]["patchFile"] = patchFile; data["General"]["patchFile"] = patchFile;
data["Input"]["cursorState"] = cursorState;
data["Input"]["cursorHideTimeout"] = cursorHideTimeout;
data["General"]["backButtonBehavior"] = backButtonBehavior;
data["Input"]["useSpecialPad"] = useSpecialPad; data["Input"]["useSpecialPad"] = useSpecialPad;
data["Input"]["specialPadClass"] = specialPadClass; data["Input"]["specialPadClass"] = specialPadClass;
data["GPU"]["screenWidth"] = screenWidth; data["GPU"]["screenWidth"] = screenWidth;
@ -604,6 +648,9 @@ void setDefaultValues() {
isFullscreen = false; isFullscreen = false;
playBGM = false; playBGM = false;
BGMvolume = 50; BGMvolume = 50;
enableDiscordRPC = true;
cursorState = HideCursorState::Idle;
cursorHideTimeout = 5;
screenWidth = 1280; screenWidth = 1280;
screenHeight = 720; screenHeight = 720;
logFilter = ""; logFilter = "";
@ -615,6 +662,7 @@ void setDefaultValues() {
updateChannel = "Nightly"; updateChannel = "Nightly";
} }
patchFile = ""; patchFile = "";
backButtonBehavior = "left";
useSpecialPad = false; useSpecialPad = false;
specialPadClass = 1; specialPadClass = 1;
isDebugDump = false; isDebugDump = false;

View File

@ -8,6 +8,9 @@
#include "types.h" #include "types.h"
namespace Config { namespace Config {
enum HideCursorState : s16 { Never, Idle, Always };
void load(const std::filesystem::path& path); void load(const std::filesystem::path& path);
void save(const std::filesystem::path& path); void save(const std::filesystem::path& path);
void loadArgs(int& argc, char* argv[]); void loadArgs(int& argc, char* argv[]);
@ -16,12 +19,17 @@ bool isNeoMode();
bool isFullscreenMode(); bool isFullscreenMode();
bool getPlayBGM(); bool getPlayBGM();
int getBGMvolume(); int getBGMvolume();
bool getEnableDiscordRPC();
s16 getCursorState();
int getCursorHideTimeout();
std::string getLogFilter(); std::string getLogFilter();
std::string getLogType(); std::string getLogType();
std::string getUserName(); std::string getUserName();
std::string getUpdateChannel(); std::string getUpdateChannel();
std::string getPatchFile(); std::string getPatchFile();
std::string getBackButtonBehavior();
bool getUseSpecialPad(); bool getUseSpecialPad();
int getSpecialPadClass(); int getSpecialPadClass();
@ -52,11 +60,15 @@ void setScreenHeight(u32 height);
void setFullscreenMode(bool enable); void setFullscreenMode(bool enable);
void setPlayBGM(bool enable); void setPlayBGM(bool enable);
void setBGMvolume(int volume); void setBGMvolume(int volume);
void setEnableDiscordRPC(bool enable);
void setCursorState(s16 cursorState);
void setCursorHideTimeout(int newcursorHideTimeout);
void setLanguage(u32 language); 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 setPatchFile(const std::string& fileName); void setPatchFile(const std::string& fileName);
void setBackButtonBehavior(const std::string& type);
void setUseSpecialPad(bool use); void setUseSpecialPad(bool use);
void setSpecialPadClass(int type); void setSpecialPadClass(int type);

View File

@ -1,43 +0,0 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
#include <ctime>
#include "common/discord.h"
namespace Discord {
void RPC::init() {
DiscordEventHandlers handlers{};
Discord_Initialize("1139939140494971051", &handlers, 1, nullptr);
startTimestamp = time(nullptr);
enabled = true;
}
void RPC::update(Discord::RPCStatus status, const std::string& game) {
DiscordRichPresence rpc{};
if (status == Discord::RPCStatus::Playing) {
rpc.details = "Playing a game";
rpc.state = game.c_str();
} else {
rpc.details = "Idle";
}
rpc.largeImageKey = "shadps4";
rpc.largeImageText = "ShadPS4 is a PS4 emulator";
rpc.startTimestamp = startTimestamp;
Discord_UpdatePresence(&rpc);
}
void RPC::stop() {
if (enabled) {
enabled = false;
Discord_ClearPresence();
Discord_Shutdown();
}
}
} // namespace Discord

View File

@ -0,0 +1,57 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include <cstring>
#include <ctime>
#include "src/common/discord_rpc_handler.h"
namespace DiscordRPCHandler {
void RPC::init() {
DiscordEventHandlers handlers{};
Discord_Initialize("1139939140494971051", &handlers, 1, nullptr);
startTimestamp = time(nullptr);
rpcEnabled = true;
}
void RPC::setStatusIdling() {
DiscordRichPresence rpc{};
rpc.largeImageKey = "https://github.com/shadps4-emu/shadPS4/raw/main/.github/shadps4.png";
rpc.largeImageText = "shadPS4 is a PS4 emulator";
rpc.startTimestamp = startTimestamp;
rpc.details = "Idle";
status = RPCStatus::Idling;
Discord_UpdatePresence(&rpc);
}
void RPC::setStatusPlaying(const std::string& game_name, const std::string& game_id) {
DiscordRichPresence rpc{};
rpc.details = "Playing";
rpc.state = game_name.c_str();
std::string largeImageUrl =
"https://store.playstation.com/store/api/chihiro/00_09_000/titlecontainer/US/en/999/" +
game_id + "_00/image";
rpc.largeImageKey = largeImageUrl.c_str();
rpc.largeImageText = game_name.c_str();
rpc.startTimestamp = startTimestamp;
status = RPCStatus::Playing;
Discord_UpdatePresence(&rpc);
}
void RPC::shutdown() {
if (rpcEnabled) {
rpcEnabled = false;
Discord_ClearPresence();
Discord_Shutdown();
}
}
bool RPC::getRPCEnabled() {
return rpcEnabled;
}
} // namespace DiscordRPCHandler

View File

@ -7,7 +7,7 @@
#include <string> #include <string>
#include <discord_rpc.h> #include <discord_rpc.h>
namespace Discord { namespace DiscordRPCHandler {
enum class RPCStatus { enum class RPCStatus {
Idling, Idling,
@ -16,12 +16,15 @@ enum class RPCStatus {
class RPC { class RPC {
std::uint64_t startTimestamp; std::uint64_t startTimestamp;
bool enabled = false; bool rpcEnabled = false;
RPCStatus status;
public: public:
void init(); void init();
void update(RPCStatus status, const std::string& title); void setStatusIdling();
void stop(); void setStatusPlaying(const std::string& game_name, const std::string& game_id);
void shutdown();
bool getRPCEnabled();
}; };
} // namespace Discord } // namespace DiscordRPCHandler

View File

@ -25,7 +25,7 @@ asm(".zerofill GUEST_SYSTEM,GUEST_SYSTEM,__guest_system,0xFBFC00000");
namespace Core { namespace Core {
static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE; static constexpr size_t BackingSize = SCE_KERNEL_MAIN_DMEM_SIZE_PRO;
#ifdef _WIN32 #ifdef _WIN32

View File

@ -227,6 +227,12 @@ void PSF::AddBinary(std::string key, std::vector<u8> value, bool update) {
map_binaries.emplace(entry_list.size() - 1, std::move(value)); map_binaries.emplace(entry_list.size() - 1, std::move(value));
} }
void PSF::AddBinary(std::string key, uint64_t value, bool update) {
std::vector<u8> data(8);
std::memcpy(data.data(), &value, 8);
return AddBinary(std::move(key), std::move(data), update);
}
void PSF::AddString(std::string key, std::string value, bool update) { void PSF::AddString(std::string key, std::string value, bool update) {
auto [it, index] = FindEntry(key); auto [it, index] = FindEntry(key);
bool exist = it != entry_list.end(); bool exist = it != entry_list.end();

View File

@ -67,6 +67,7 @@ public:
std::optional<s32> GetInteger(std::string_view key) const; std::optional<s32> GetInteger(std::string_view key) const;
void AddBinary(std::string key, std::vector<u8> value, bool update = false); void AddBinary(std::string key, std::vector<u8> value, bool update = false);
void AddBinary(std::string key, uint64_t value, bool update = false); // rsv4 format
void AddString(std::string key, std::string value, bool update = false); void AddString(std::string key, std::string value, bool update = false);
void AddInteger(std::string key, s32 value, bool update = false); void AddInteger(std::string key, s32 value, bool update = false);

View File

@ -7,6 +7,8 @@
#include "common/types.h" #include "common/types.h"
constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE = 5056_MB; // ~ 5GB
// TODO: Confirm this value on hardware.
constexpr u64 SCE_KERNEL_MAIN_DMEM_SIZE_PRO = 5568_MB; // ~ 5.5GB
namespace Libraries::Kernel { namespace Libraries::Kernel {

View File

@ -18,6 +18,8 @@
namespace Libraries::Net { namespace Libraries::Net {
static thread_local int32_t net_errno = 0;
int PS4_SYSV_ABI in6addr_any() { int PS4_SYSV_ABI in6addr_any() {
LOG_ERROR(Lib_Net, "(STUBBED) called"); LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK; return ORBIS_OK;
@ -563,9 +565,9 @@ int PS4_SYSV_ABI sceNetEpollWait() {
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceNetErrnoLoc() { int* PS4_SYSV_ABI sceNetErrnoLoc() {
LOG_ERROR(Lib_Net, "(STUBBED) called"); LOG_ERROR(Lib_Net, "(STUBBED) called");
return ORBIS_OK; return &net_errno;
} }
int PS4_SYSV_ABI sceNetEtherNtostr() { int PS4_SYSV_ABI sceNetEtherNtostr() {

View File

@ -136,7 +136,7 @@ int PS4_SYSV_ABI sceNetEpollControl();
int PS4_SYSV_ABI sceNetEpollCreate(); int PS4_SYSV_ABI sceNetEpollCreate();
int PS4_SYSV_ABI sceNetEpollDestroy(); int PS4_SYSV_ABI sceNetEpollDestroy();
int PS4_SYSV_ABI sceNetEpollWait(); int PS4_SYSV_ABI sceNetEpollWait();
int PS4_SYSV_ABI sceNetErrnoLoc(); int* PS4_SYSV_ABI sceNetErrnoLoc();
int PS4_SYSV_ABI sceNetEtherNtostr(); int PS4_SYSV_ABI sceNetEtherNtostr();
int PS4_SYSV_ABI sceNetEtherStrton(); int PS4_SYSV_ABI sceNetEtherStrton();
int PS4_SYSV_ABI sceNetEventCallbackCreate(); int PS4_SYSV_ABI sceNetEventCallbackCreate();

View File

@ -368,12 +368,13 @@ int PS4_SYSV_ABI scePadReadState(s32 handle, OrbisPadData* pData) {
pData->angularVelocity.x = 0.0f; pData->angularVelocity.x = 0.0f;
pData->angularVelocity.y = 0.0f; pData->angularVelocity.y = 0.0f;
pData->angularVelocity.z = 0.0f; pData->angularVelocity.z = 0.0f;
pData->touchData.touchNum = 0; pData->touchData.touchNum =
pData->touchData.touch[0].x = 0; (state.touchpad[0].state ? 1 : 0) + (state.touchpad[1].state ? 1 : 0);
pData->touchData.touch[0].y = 0; pData->touchData.touch[0].x = state.touchpad[0].x;
pData->touchData.touch[0].y = state.touchpad[0].y;
pData->touchData.touch[0].id = 1; pData->touchData.touch[0].id = 1;
pData->touchData.touch[1].x = 0; pData->touchData.touch[1].x = state.touchpad[1].x;
pData->touchData.touch[1].y = 0; pData->touchData.touch[1].y = state.touchpad[1].y;
pData->touchData.touch[1].id = 2; pData->touchData.touch[1].id = 2;
pData->timestamp = state.time; pData->timestamp = state.time;
pData->connected = true; // isConnected; //TODO fix me proper pData->connected = true; // isConnected; //TODO fix me proper

View File

@ -12,9 +12,9 @@
#include "core/file_sys/fs.h" #include "core/file_sys/fs.h"
#include "save_instance.h" #include "save_instance.h"
constexpr u32 OrbisSaveDataBlocksMax = 32768; // 1 GiB constexpr auto OrbisSaveDataBlocksMin2 = 96; // 3MiB
constexpr auto OrbisSaveDataBlocksMax = 32768; // 1 GiB
constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save constexpr std::string_view sce_sys = "sce_sys"; // system folder inside save
constexpr std::string_view max_block_file_name = "max_block.txt";
static Core::FileSys::MntPoints* g_mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); static Core::FileSys::MntPoints* g_mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
@ -58,18 +58,13 @@ std::filesystem::path SaveInstance::MakeDirSavePath(OrbisUserServiceUserId user_
game_serial / dir_name; game_serial / dir_name;
} }
int SaveInstance::GetMaxBlocks(const std::filesystem::path& save_path) { uint64_t SaveInstance::GetMaxBlockFromSFO(const PSF& psf) {
Common::FS::IOFile max_blocks_file{save_path / sce_sys / max_block_file_name, const auto vec = psf.GetBinary(std::string{SaveParams::SAVEDATA_BLOCKS});
Common::FS::FileAccessMode::Read}; if (!vec.has_value()) {
int max_blocks = 0; return OrbisSaveDataBlocksMax;
if (max_blocks_file.IsOpen()) {
max_blocks = std::atoi(max_blocks_file.ReadString(16).c_str());
} }
if (max_blocks <= 0) { auto value = vec.value();
max_blocks = OrbisSaveDataBlocksMax; return *(uint64_t*)value.data();
}
return max_blocks;
} }
std::filesystem::path SaveInstance::GetParamSFOPath(const std::filesystem::path& dir_path) { std::filesystem::path SaveInstance::GetParamSFOPath(const std::filesystem::path& dir_path) {
@ -92,13 +87,15 @@ void SaveInstance::SetupDefaultParamSFO(PSF& param_sfo, std::string dir_name,
P(String, SaveParams::SAVEDATA_DIRECTORY, std::move(dir_name)); P(String, SaveParams::SAVEDATA_DIRECTORY, std::move(dir_name));
P(Integer, SaveParams::SAVEDATA_LIST_PARAM, 0); P(Integer, SaveParams::SAVEDATA_LIST_PARAM, 0);
P(String, SaveParams::TITLE_ID, std::move(game_serial)); P(String, SaveParams::TITLE_ID, std::move(game_serial));
P(Binary, SaveParams::SAVEDATA_BLOCKS, {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00});
#undef P #undef P
} }
SaveInstance::SaveInstance(int slot_num, OrbisUserServiceUserId user_id, std::string _game_serial, SaveInstance::SaveInstance(int slot_num, OrbisUserServiceUserId user_id, std::string _game_serial,
std::string_view _dir_name, int max_blocks) std::string_view _dir_name, int max_blocks)
: slot_num(slot_num), user_id(user_id), game_serial(std::move(_game_serial)), : slot_num(slot_num), user_id(user_id), game_serial(std::move(_game_serial)),
dir_name(_dir_name), max_blocks(max_blocks) { dir_name(_dir_name),
max_blocks(std::clamp(max_blocks, OrbisSaveDataBlocksMin2, OrbisSaveDataBlocksMax)) {
ASSERT(slot_num >= 0 && slot_num < 16); ASSERT(slot_num >= 0 && slot_num < 16);
save_path = MakeDirSavePath(user_id, game_serial, dir_name); save_path = MakeDirSavePath(user_id, game_serial, dir_name);
@ -187,7 +184,7 @@ void SaveInstance::SetupAndMount(bool read_only, bool copy_icon, bool ignore_cor
} }
} }
max_blocks = GetMaxBlocks(save_path); max_blocks = static_cast<int>(GetMaxBlockFromSFO(param_sfo));
g_mnt->Mount(save_path, mount_point, read_only); g_mnt->Mount(save_path, mount_point, read_only);
mounted = true; mounted = true;
@ -217,16 +214,13 @@ void SaveInstance::CreateFiles() {
fs::create_directories(sce_sys_dir); fs::create_directories(sce_sys_dir);
SetupDefaultParamSFO(param_sfo, dir_name, game_serial); SetupDefaultParamSFO(param_sfo, dir_name, game_serial);
param_sfo.AddBinary(std::string{SaveParams::SAVEDATA_BLOCKS}, max_blocks, true);
const bool ok = param_sfo.Encode(param_sfo_path); const bool ok = param_sfo.Encode(param_sfo_path);
if (!ok) { if (!ok) {
throw std::filesystem::filesystem_error("Failed to write param.sfo", param_sfo_path, throw std::filesystem::filesystem_error("Failed to write param.sfo", param_sfo_path,
std::make_error_code(std::errc::permission_denied)); std::make_error_code(std::errc::permission_denied));
} }
Common::FS::IOFile max_block{sce_sys_dir / max_block_file_name,
Common::FS::FileAccessMode::Write};
max_block.WriteString(std::to_string(max_blocks == 0 ? OrbisSaveDataBlocksMax : max_blocks));
} }
} // namespace Libraries::SaveData } // namespace Libraries::SaveData

View File

@ -62,7 +62,7 @@ public:
std::string_view game_serial, std::string_view game_serial,
std::string_view dir_name); std::string_view dir_name);
static int GetMaxBlocks(const std::filesystem::path& save_path); static uint64_t GetMaxBlockFromSFO(const PSF& psf);
// Get param.sfo path from a dir_path generated by MakeDirSavePath // Get param.sfo path from a dir_path generated by MakeDirSavePath
static std::filesystem::path GetParamSFOPath(const std::filesystem::path& dir_path); static std::filesystem::path GetParamSFOPath(const std::filesystem::path& dir_path);

View File

@ -445,7 +445,7 @@ static Error saveDataMount(const OrbisSaveDataMount2* mount_info,
fs::create_directories(root_save); fs::create_directories(root_save);
const auto available = fs::space(root_save).available; const auto available = fs::space(root_save).available;
auto requested_size = mount_info->blocks * OrbisSaveDataBlockSize; auto requested_size = save_instance.GetMaxBlocks() * OrbisSaveDataBlockSize;
if (requested_size > available) { if (requested_size > available) {
mount_result->required_blocks = (requested_size - available) / OrbisSaveDataBlockSize; mount_result->required_blocks = (requested_size - available) / OrbisSaveDataBlockSize;
return Error::NO_SPACE_FS; return Error::NO_SPACE_FS;
@ -830,10 +830,11 @@ Error PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond
LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", fmt::UTF(sfo_path.u8string())); LOG_ERROR(Lib_SaveData, "Failed to read SFO: {}", fmt::UTF(sfo_path.u8string()));
ASSERT_MSG(false, "Failed to read SFO"); ASSERT_MSG(false, "Failed to read SFO");
} }
map_dir_sfo.emplace(dir_name, std::move(sfo));
size_t size = Common::FS::GetDirectorySize(dir_path); size_t size = Common::FS::GetDirectorySize(dir_path);
size_t total = SaveInstance::GetMaxBlocks(dir_path); size_t total = SaveInstance::GetMaxBlockFromSFO(sfo);
map_dir_sfo.emplace(dir_name, std::move(sfo));
map_free_size.emplace(dir_name, total - size / OrbisSaveDataBlockSize); map_free_size.emplace(dir_name, total - size / OrbisSaveDataBlockSize);
map_max_blocks.emplace(dir_name, total); map_max_blocks.emplace(dir_name, total);
} }

View File

@ -3,6 +3,7 @@
#include "common/alignment.h" #include "common/alignment.h"
#include "common/assert.h" #include "common/assert.h"
#include "common/config.h"
#include "common/debug.h" #include "common/debug.h"
#include "core/libraries/error_codes.h" #include "core/libraries/error_codes.h"
#include "core/libraries/kernel/memory_management.h" #include "core/libraries/kernel/memory_management.h"
@ -39,8 +40,10 @@ MemoryManager::MemoryManager() {
MemoryManager::~MemoryManager() = default; MemoryManager::~MemoryManager() = default;
void MemoryManager::SetupMemoryRegions(u64 flexible_size) { void MemoryManager::SetupMemoryRegions(u64 flexible_size) {
const auto total_size =
Config::isNeoMode() ? SCE_KERNEL_MAIN_DMEM_SIZE_PRO : SCE_KERNEL_MAIN_DMEM_SIZE;
total_flexible_size = flexible_size; total_flexible_size = flexible_size;
total_direct_size = SCE_KERNEL_MAIN_DMEM_SIZE - flexible_size; total_direct_size = total_size - flexible_size;
// Insert an area that covers direct memory physical block. // Insert an area that covers direct memory physical block.
// Note that this should never be called after direct memory allocations have been made. // Note that this should never be called after direct memory allocations have been made.

View File

@ -11,6 +11,7 @@
#include "common/memory_patcher.h" #include "common/memory_patcher.h"
#endif #endif
#include "common/assert.h" #include "common/assert.h"
#include "common/discord_rpc_handler.h"
#include "common/elf_info.h" #include "common/elf_info.h"
#include "common/ntapi.h" #include "common/ntapi.h"
#include "common/path_util.h" #include "common/path_util.h"
@ -58,6 +59,7 @@ Emulator::Emulator() {
LOG_INFO(Loader, "Branch {}", Common::g_scm_branch); LOG_INFO(Loader, "Branch {}", Common::g_scm_branch);
LOG_INFO(Loader, "Description {}", Common::g_scm_desc); LOG_INFO(Loader, "Description {}", Common::g_scm_desc);
LOG_INFO(Config, "General Logtype: {}", Config::getLogType());
LOG_INFO(Config, "General isNeo: {}", Config::isNeoMode()); LOG_INFO(Config, "General isNeo: {}", Config::isNeoMode());
LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu()); LOG_INFO(Config, "GPU isNullGpu: {}", Config::nullGpu());
LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders()); LOG_INFO(Config, "GPU shouldDumpShaders: {}", Config::dumpShaders());
@ -209,6 +211,15 @@ void Emulator::Run(const std::filesystem::path& file) {
} }
} }
// Discord RPC
if (Config::getEnableDiscordRPC()) {
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();
if (rpc->getRPCEnabled() == false) {
rpc->init();
}
rpc->setStatusPlaying(game_info.title, id);
}
// start execution // start execution
std::jthread mainthread = std::jthread mainthread =
std::jthread([this](std::stop_token stop_token) { linker->Execute(); }); std::jthread([this](std::stop_token stop_token) { linker->Execute(); });

View File

@ -4,6 +4,7 @@
// Based on imgui_impl_sdl3.cpp from Dear ImGui repository // Based on imgui_impl_sdl3.cpp from Dear ImGui repository
#include <imgui.h> #include <imgui.h>
#include "common/config.h"
#include "imgui_impl_sdl3.h" #include "imgui_impl_sdl3.h"
// SDL // SDL
@ -36,6 +37,8 @@ struct SdlData {
SDL_Cursor* mouse_cursors[ImGuiMouseCursor_COUNT]{}; SDL_Cursor* mouse_cursors[ImGuiMouseCursor_COUNT]{};
SDL_Cursor* mouse_last_cursor{}; SDL_Cursor* mouse_last_cursor{};
int mouse_pending_leave_frame{}; int mouse_pending_leave_frame{};
ImVec2 prev_mouse_pos{0, 0};
Uint64 lastCursorMoveTime{};
// Gamepad handling // Gamepad handling
ImVector<SDL_Gamepad*> gamepads{}; ImVector<SDL_Gamepad*> gamepads{};
@ -371,6 +374,13 @@ bool ProcessEvent(const SDL_Event* event) {
? ImGuiMouseSource_TouchScreen ? ImGuiMouseSource_TouchScreen
: ImGuiMouseSource_Mouse); : ImGuiMouseSource_Mouse);
io.AddMousePosEvent(mouse_pos.x, mouse_pos.y); io.AddMousePosEvent(mouse_pos.x, mouse_pos.y);
if (mouse_pos.x != bd->prev_mouse_pos.x || mouse_pos.y != bd->prev_mouse_pos.y) {
bd->prev_mouse_pos.x = mouse_pos.x;
bd->prev_mouse_pos.y = mouse_pos.y;
if (Config::getCursorState() == Config::HideCursorState::Idle) {
bd->lastCursorMoveTime = bd->time;
}
}
return true; return true;
} }
case SDL_EVENT_MOUSE_WHEEL: { case SDL_EVENT_MOUSE_WHEEL: {
@ -447,6 +457,7 @@ bool ProcessEvent(const SDL_Event* event) {
return false; return false;
bd->mouse_window_id = event->window.windowID; bd->mouse_window_id = event->window.windowID;
bd->mouse_pending_leave_frame = 0; bd->mouse_pending_leave_frame = 0;
bd->lastCursorMoveTime = bd->time;
return true; return true;
} }
// - In some cases, when detaching a window from main viewport SDL may send // - In some cases, when detaching a window from main viewport SDL may send
@ -459,6 +470,7 @@ bool ProcessEvent(const SDL_Event* event) {
if (GetViewportForWindowId(event->window.windowID) == NULL) if (GetViewportForWindowId(event->window.windowID) == NULL)
return false; return false;
bd->mouse_pending_leave_frame = ImGui::GetFrameCount() + 1; bd->mouse_pending_leave_frame = ImGui::GetFrameCount() + 1;
bd->lastCursorMoveTime = bd->time;
return true; return true;
} }
case SDL_EVENT_WINDOW_FOCUS_GAINED: case SDL_EVENT_WINDOW_FOCUS_GAINED:
@ -581,7 +593,7 @@ static void UpdateMouseData() {
// (below) // (below)
// SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries // SDL_CaptureMouse() let the OS know e.g. that our imgui drag outside the SDL window boundaries
// shouldn't e.g. trigger other operations outside // shouldn't e.g. trigger other operations outside
SDL_CaptureMouse((bd->mouse_buttons_down != 0) ? SDL_TRUE : SDL_FALSE); SDL_CaptureMouse((bd->mouse_buttons_down != 0) ? true : false);
SDL_Window* focused_window = SDL_GetKeyboardFocus(); SDL_Window* focused_window = SDL_GetKeyboardFocus();
const bool is_app_focused = (bd->window == focused_window); const bool is_app_focused = (bd->window == focused_window);
@ -600,7 +612,18 @@ static void UpdateMouseData() {
int window_x, window_y; int window_x, window_y;
SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global); SDL_GetGlobalMouseState(&mouse_x_global, &mouse_y_global);
SDL_GetWindowPosition(focused_window, &window_x, &window_y); SDL_GetWindowPosition(focused_window, &window_x, &window_y);
io.AddMousePosEvent(mouse_x_global - (float)window_x, mouse_y_global - (float)window_y); mouse_x_global -= (float)window_x;
mouse_y_global -= (float)window_y;
io.AddMousePosEvent(mouse_x_global, mouse_y_global);
// SDL_EVENT_MOUSE_MOTION isn't triggered before the first frame is rendered
// force update the prev_cursor coords
if (mouse_x_global != bd->prev_mouse_pos.x || mouse_y_global != bd->prev_mouse_pos.y &&
bd->prev_mouse_pos.y == 0 &&
bd->prev_mouse_pos.x == 0) {
bd->prev_mouse_pos.x = mouse_x_global;
bd->prev_mouse_pos.y = mouse_y_global;
bd->lastCursorMoveTime = bd->time;
}
} }
} }
} }
@ -611,10 +634,25 @@ static void UpdateMouseCursor() {
return; return;
SdlData* bd = GetBackendData(); SdlData* bd = GetBackendData();
s16 cursorState = Config::getCursorState();
ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor(); ImGuiMouseCursor imgui_cursor = ImGui::GetMouseCursor();
if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None) { if (io.MouseDrawCursor || imgui_cursor == ImGuiMouseCursor_None ||
cursorState == Config::HideCursorState::Always) {
// Hide OS mouse cursor if imgui is drawing it or if it wants no cursor // Hide OS mouse cursor if imgui is drawing it or if it wants no cursor
SDL_HideCursor(); SDL_HideCursor();
} else if (cursorState == Config::HideCursorState::Idle &&
bd->time - bd->lastCursorMoveTime >=
Config::getCursorHideTimeout() * SDL_GetPerformanceFrequency()) {
bool wasCursorVisible = SDL_CursorVisible();
SDL_HideCursor();
if (wasCursorVisible) {
SDL_WarpMouseInWindow(SDL_GetKeyboardFocus(), bd->prev_mouse_pos.x,
bd->prev_mouse_pos.y); // Force refresh the cursor state
}
} else { } else {
// Show OS mouse cursor // Show OS mouse cursor
SDL_Cursor* expected_cursor = bd->mouse_cursors[imgui_cursor] SDL_Cursor* expected_cursor = bd->mouse_cursors[imgui_cursor]

View File

@ -374,11 +374,17 @@ void CheckUpdate::Install() {
QString userPath; QString userPath;
Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir)); Common::FS::PathToQString(userPath, Common::FS::GetUserPath(Common::FS::PathType::UserDir));
QString startingUpdate = tr("Starting Update...");
QString tempDirPath = userPath + "/temp_download_update";
QString rootPath; QString rootPath;
Common::FS::PathToQString(rootPath, std::filesystem::current_path()); Common::FS::PathToQString(rootPath, std::filesystem::current_path());
QString tempDirPath = userPath + "/temp_download_update";
QString startingUpdate = tr("Starting Update...");
QString binaryStartingUpdate;
for (QChar c : startingUpdate) {
binaryStartingUpdate.append(QString::number(c.unicode(), 2).rightJustified(16, '0'));
}
QString scriptContent; QString scriptContent;
QString scriptFileName; QString scriptFileName;
QStringList arguments; QStringList arguments;
@ -389,7 +395,13 @@ void CheckUpdate::Install() {
scriptFileName = tempDirPath + "/update.ps1"; scriptFileName = tempDirPath + "/update.ps1";
scriptContent = QStringLiteral( scriptContent = QStringLiteral(
"Set-ExecutionPolicy Bypass -Scope Process -Force\n" "Set-ExecutionPolicy Bypass -Scope Process -Force\n"
"Write-Output '%1'\n" "$binaryStartingUpdate = '%1'\n"
"$chars = @()\n"
"for ($i = 0; $i -lt $binaryStartingUpdate.Length; $i += 16) {\n"
" $chars += [char]([convert]::ToInt32($binaryStartingUpdate.Substring($i, 16), 2))\n"
"}\n"
"$startingUpdate = -join $chars\n"
"Write-Output $startingUpdate\n"
"Expand-Archive -Path '%2\\temp_download_update.zip' -DestinationPath '%2' -Force\n" "Expand-Archive -Path '%2\\temp_download_update.zip' -DestinationPath '%2' -Force\n"
"Start-Sleep -Seconds 3\n" "Start-Sleep -Seconds 3\n"
"Copy-Item -Recurse -Force '%2\\*' '%3\\'\n" "Copy-Item -Recurse -Force '%2\\*' '%3\\'\n"
@ -454,6 +466,10 @@ void CheckUpdate::Install() {
" sleep 2\n" " sleep 2\n"
" extract_file\n" " extract_file\n"
" sleep 2\n" " sleep 2\n"
" if pgrep -f \"Shadps4-qt.AppImage\" > /dev/null; then\n"
" pkill -f \"Shadps4-qt.AppImage\"\n"
" sleep 2\n"
" fi\n"
" cp -r \"%2/\"* \"%3/\"\n" " cp -r \"%2/\"* \"%3/\"\n"
" sleep 2\n" " sleep 2\n"
" rm \"%3/update.sh\"\n" " rm \"%3/update.sh\"\n"
@ -508,7 +524,12 @@ void CheckUpdate::Install() {
QFile scriptFile(scriptFileName); QFile scriptFile(scriptFileName);
if (scriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) { if (scriptFile.open(QIODevice::WriteOnly | QIODevice::Text)) {
QTextStream out(&scriptFile); QTextStream out(&scriptFile);
#ifdef Q_OS_WIN
out << scriptContent.arg(binaryStartingUpdate).arg(tempDirPath).arg(rootPath);
#endif
#if defined(Q_OS_LINUX) || defined(Q_OS_MAC)
out << scriptContent.arg(startingUpdate).arg(tempDirPath).arg(rootPath); out << scriptContent.arg(startingUpdate).arg(tempDirPath).arg(rootPath);
#endif
scriptFile.close(); scriptFile.close();
// Make the script executable on Unix-like systems // Make the script executable on Unix-like systems

View File

@ -69,6 +69,14 @@ bool MainWindow::Init() {
QString statusMessage = QString statusMessage =
"Games: " + QString::number(numGames) + " (" + QString::number(duration.count()) + "ms)"; "Games: " + QString::number(numGames) + " (" + QString::number(duration.count()) + "ms)";
statusBar->showMessage(statusMessage); statusBar->showMessage(statusMessage);
// Initialize Discord RPC
if (Config::getEnableDiscordRPC()) {
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();
rpc->init();
rpc->setStatusIdling();
}
return true; return true;
} }

View File

@ -9,6 +9,7 @@
#include "background_music_player.h" #include "background_music_player.h"
#include "common/config.h" #include "common/config.h"
#include "common/discord_rpc_handler.h"
#include "common/path_util.h" #include "common/path_util.h"
#include "core/file_format/psf.h" #include "core/file_format/psf.h"
#include "core/file_sys/fs.h" #include "core/file_sys/fs.h"

View File

@ -47,6 +47,8 @@ QStringList languageNames = {"Arabic",
const QVector<int> languageIndexes = {21, 23, 14, 6, 18, 1, 12, 22, 2, 4, 25, 24, 29, 5, 0, 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, 28}; 9, 15, 16, 17, 7, 26, 8, 11, 20, 3, 13, 27, 10, 19, 28};
QStringList hideCursorStates = {"Never", "Idle", "Always"};
SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidget* parent) SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidget* parent)
: QDialog(parent), ui(new Ui::SettingsDialog) { : QDialog(parent), ui(new Ui::SettingsDialog) {
ui->setupUi(this); ui->setupUi(this);
@ -67,6 +69,8 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
completer->setCaseSensitivity(Qt::CaseInsensitive); completer->setCaseSensitivity(Qt::CaseInsensitive);
ui->consoleLanguageComboBox->setCompleter(completer); ui->consoleLanguageComboBox->setCompleter(completer);
ui->hideCursorComboBox->addItems(hideCursorStates);
InitializeEmulatorLanguages(); InitializeEmulatorLanguages();
LoadValuesFromConfig(); LoadValuesFromConfig();
@ -98,6 +102,15 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setText(tr("Restore Defaults")); ui->buttonBox->button(QDialogButtonBox::RestoreDefaults)->setText(tr("Restore Defaults"));
ui->buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close")); ui->buttonBox->button(QDialogButtonBox::Close)->setText(tr("Close"));
ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Left"), "left");
ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Center"), "center");
ui->backButtonBehaviorComboBox->addItem(tr("Touchpad Right"), "right");
ui->backButtonBehaviorComboBox->addItem(tr("None"), "none");
QString currentBackButtonBehavior = QString::fromStdString(Config::getBackButtonBehavior());
int index = ui->backButtonBehaviorComboBox->findData(currentBackButtonBehavior);
ui->backButtonBehaviorComboBox->setCurrentIndex(index != -1 ? index : 0);
connect(ui->tabWidgetSettings, &QTabWidget::currentChanged, this, connect(ui->tabWidgetSettings, &QTabWidget::currentChanged, this,
[this]() { ui->buttonBox->button(QDialogButtonBox::Close)->setFocus(); }); [this]() { ui->buttonBox->button(QDialogButtonBox::Close)->setFocus(); });
@ -151,6 +164,37 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
Config::setBGMvolume(val); Config::setBGMvolume(val);
BackgroundMusicPlayer::getInstance().setVolume(val); BackgroundMusicPlayer::getInstance().setVolume(val);
}); });
connect(ui->discordRPCCheckbox, &QCheckBox::stateChanged, this, [](int val) {
Config::setEnableDiscordRPC(val);
auto* rpc = Common::Singleton<DiscordRPCHandler::RPC>::Instance();
if (val == Qt::Checked) {
rpc->init();
rpc->setStatusIdling();
} else {
rpc->shutdown();
}
});
connect(ui->backButtonBehaviorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, [this](int index) {
if (index >= 0 && index < ui->backButtonBehaviorComboBox->count()) {
QString data = ui->backButtonBehaviorComboBox->itemData(index).toString();
Config::setBackButtonBehavior(data.toStdString());
}
});
}
// Input TAB
{
connect(ui->hideCursorComboBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this,
[this](s16 index) {
Config::setCursorState(index);
OnCursorStateChanged(index);
});
connect(ui->idleTimeoutSpinBox, &QSpinBox::valueChanged, this,
[](int index) { Config::setCursorHideTimeout(index); });
} }
// GPU TAB // GPU TAB
@ -204,6 +248,7 @@ SettingsDialog::SettingsDialog(std::span<const QString> physical_devices, QWidge
ui->logFilter->installEventFilter(this); ui->logFilter->installEventFilter(this);
ui->updaterGroupBox->installEventFilter(this); ui->updaterGroupBox->installEventFilter(this);
ui->GUIgroupBox->installEventFilter(this); ui->GUIgroupBox->installEventFilter(this);
ui->backButtonBehaviorGroupBox->installEventFilter(this);
// Graphics // Graphics
ui->graphicsAdapterGroupBox->installEventFilter(this); ui->graphicsAdapterGroupBox->installEventFilter(this);
@ -228,6 +273,9 @@ void SettingsDialog::LoadValuesFromConfig() {
std::find(languageIndexes.begin(), languageIndexes.end(), Config::GetLanguage())) % std::find(languageIndexes.begin(), languageIndexes.end(), Config::GetLanguage())) %
languageIndexes.size()); languageIndexes.size());
ui->emulatorLanguageComboBox->setCurrentIndex(languages[Config::getEmulatorLanguage()]); ui->emulatorLanguageComboBox->setCurrentIndex(languages[Config::getEmulatorLanguage()]);
ui->hideCursorComboBox->setCurrentIndex(Config::getCursorState());
OnCursorStateChanged(Config::getCursorState());
ui->idleTimeoutSpinBox->setValue(Config::getCursorHideTimeout());
ui->graphicsAdapterBox->setCurrentIndex(Config::getGpuId() + 1); ui->graphicsAdapterBox->setCurrentIndex(Config::getGpuId() + 1);
ui->widthSpinBox->setValue(Config::getScreenWidth()); ui->widthSpinBox->setValue(Config::getScreenWidth());
ui->heightSpinBox->setValue(Config::getScreenHeight()); ui->heightSpinBox->setValue(Config::getScreenHeight());
@ -236,6 +284,7 @@ void SettingsDialog::LoadValuesFromConfig() {
ui->nullGpuCheckBox->setChecked(Config::nullGpu()); ui->nullGpuCheckBox->setChecked(Config::nullGpu());
ui->playBGMCheckBox->setChecked(Config::getPlayBGM()); ui->playBGMCheckBox->setChecked(Config::getPlayBGM());
ui->BGMVolumeSlider->setValue((Config::getBGMvolume())); ui->BGMVolumeSlider->setValue((Config::getBGMvolume()));
ui->discordRPCCheckbox->setChecked(Config::getEnableDiscordRPC());
ui->fullscreenCheckBox->setChecked(Config::isFullscreenMode()); ui->fullscreenCheckBox->setChecked(Config::isFullscreenMode());
ui->showSplashCheckBox->setChecked(Config::showSplash()); ui->showSplashCheckBox->setChecked(Config::showSplash());
ui->ps4proCheckBox->setChecked(Config::isNeoMode()); ui->ps4proCheckBox->setChecked(Config::isNeoMode());
@ -258,6 +307,10 @@ void SettingsDialog::LoadValuesFromConfig() {
} }
} }
ui->updateComboBox->setCurrentText(QString::fromStdString(updateChannel)); ui->updateComboBox->setCurrentText(QString::fromStdString(updateChannel));
QString backButtonBehavior = QString::fromStdString(Config::getBackButtonBehavior());
int index = ui->backButtonBehaviorComboBox->findData(backButtonBehavior);
ui->backButtonBehaviorComboBox->setCurrentIndex(index != -1 ? index : 0);
} }
void SettingsDialog::InitializeEmulatorLanguages() { void SettingsDialog::InitializeEmulatorLanguages() {
@ -289,6 +342,18 @@ void SettingsDialog::OnLanguageChanged(int index) {
emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString()); emit LanguageChanged(ui->emulatorLanguageComboBox->itemData(index).toString().toStdString());
} }
void SettingsDialog::OnCursorStateChanged(s16 index) {
if (index == -1)
return;
if (index == Config::HideCursorState::Idle) {
ui->idleTimeoutGroupBox->show();
} else {
if (!ui->idleTimeoutGroupBox->isHidden()) {
ui->idleTimeoutGroupBox->hide();
}
}
}
int SettingsDialog::exec() { int SettingsDialog::exec() {
return QDialog::exec(); return QDialog::exec();
} }
@ -319,6 +384,8 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
text = tr("updaterGroupBox"); text = tr("updaterGroupBox");
} else if (elementName == "GUIgroupBox") { } else if (elementName == "GUIgroupBox") {
text = tr("GUIgroupBox"); text = tr("GUIgroupBox");
} else if (elementName == "backButtonBehaviorGroupBox") {
text = tr("backButtonBehaviorGroupBox");
} }
// Graphics // Graphics
@ -334,8 +401,6 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
text = tr("dumpShadersCheckBox"); text = tr("dumpShadersCheckBox");
} else if (elementName == "nullGpuCheckBox") { } else if (elementName == "nullGpuCheckBox") {
text = tr("nullGpuCheckBox"); text = tr("nullGpuCheckBox");
} else if (elementName == "dumpPM4CheckBox") {
text = tr("dumpPM4CheckBox");
} }
// Debug // Debug
@ -352,7 +417,7 @@ void SettingsDialog::updateNoteTextEdit(const QString& elementName) {
ui->descriptionText->setText(text.replace("\\n", "\n")); ui->descriptionText->setText(text.replace("\\n", "\n"));
} }
bool SettingsDialog::override(QObject* obj, QEvent* event) { bool SettingsDialog::eventFilter(QObject* obj, QEvent* event) {
if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) { if (event->type() == QEvent::Enter || event->type() == QEvent::Leave) {
if (qobject_cast<QWidget*>(obj)) { if (qobject_cast<QWidget*>(obj)) {
bool hovered = (event->type() == QEvent::Enter); bool hovered = (event->type() == QEvent::Enter);

View File

@ -21,7 +21,7 @@ public:
explicit SettingsDialog(std::span<const QString> physical_devices, QWidget* parent = nullptr); explicit SettingsDialog(std::span<const QString> physical_devices, QWidget* parent = nullptr);
~SettingsDialog(); ~SettingsDialog();
bool override(QObject* obj, QEvent* event); bool eventFilter(QObject* obj, QEvent* event) override;
void updateNoteTextEdit(const QString& groupName); void updateNoteTextEdit(const QString& groupName);
int exec() override; int exec() override;
@ -33,6 +33,7 @@ private:
void LoadValuesFromConfig(); void LoadValuesFromConfig();
void InitializeEmulatorLanguages(); void InitializeEmulatorLanguages();
void OnLanguageChanged(int index); void OnLanguageChanged(int index);
void OnCursorStateChanged(s16 index);
std::unique_ptr<Ui::SettingsDialog> ui; std::unique_ptr<Ui::SettingsDialog> ui;

View File

@ -34,9 +34,18 @@
<iconset> <iconset>
<normaloff>:/images/shadps4.ico</normaloff>:/images/shadps4.ico</iconset> <normaloff>:/images/shadps4.ico</normaloff>:/images/shadps4.ico</iconset>
</property> </property>
<property name="sizeGripEnabled">
<bool>false</bool>
</property>
<property name="modal">
<bool>false</bool>
</property>
<layout class="QVBoxLayout" name="settingsDialogLayout"> <layout class="QVBoxLayout" name="settingsDialogLayout">
<item> <item>
<widget class="QScrollArea" name="scrollArea"> <widget class="QScrollArea" name="scrollArea">
<property name="enabled">
<bool>true</bool>
</property>
<property name="frameShape"> <property name="frameShape">
<enum>QFrame::Shape::NoFrame</enum> <enum>QFrame::Shape::NoFrame</enum>
</property> </property>
@ -51,8 +60,8 @@
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>836</width> <width>832</width>
<height>446</height> <height>431</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -62,7 +71,7 @@
</sizepolicy> </sizepolicy>
</property> </property>
<property name="currentIndex"> <property name="currentIndex">
<number>0</number> <number>1</number>
</property> </property>
<widget class="QWidget" name="generalTab"> <widget class="QWidget" name="generalTab">
<attribute name="title"> <attribute name="title">
@ -139,6 +148,13 @@
</property> </property>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="discordRPCCheckbox">
<property name="text">
<string>Enable Discord Rich Presence</string>
</property>
</widget>
</item>
</layout> </layout>
</item> </item>
<item> <item>
@ -369,7 +385,7 @@
<x>10</x> <x>10</x>
<y>30</y> <y>30</y>
<width>241</width> <width>241</width>
<height>71</height> <height>92</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout"> <layout class="QVBoxLayout" name="verticalLayout">
@ -442,17 +458,220 @@
</layout> </layout>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer"> <layout class="QVBoxLayout" name="ControllerTabLayoutRight" stretch="1">
<item>
<widget class="QGroupBox" name="ControllerGroupBox">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="title">
<string>Controller Settings</string>
</property>
<widget class="QGroupBox" name="backButtonBehaviorGroupBox">
<property name="geometry">
<rect>
<x>12</x>
<y>30</y>
<width>241</width>
<height>65</height>
</rect>
</property>
<property name="title">
<string>Back Button Behavior</string>
</property>
<widget class="QComboBox" name="backButtonBehaviorComboBox">
<property name="geometry">
<rect>
<x>12</x>
<y>30</y>
<width>217</width>
<height>28</height>
</rect>
</property>
</widget>
</widget>
</widget>
</item>
</layout>
</item>
</layout>
</item>
</layout>
</widget>
<widget class="QWidget" name="inputTab">
<attribute name="title">
<string>Input</string>
</attribute>
<layout class="QVBoxLayout" name="inputTabVLayout" stretch="0,0">
<item>
<layout class="QHBoxLayout" name="inputTabHLayoutTop" stretch="1,1,1">
<item>
<layout class="QVBoxLayout" name="cursorTabLayoutLeft">
<item>
<widget class="QGroupBox" name="HideCursor">
<property name="title">
<string>Cursor</string>
</property>
<layout class="QVBoxLayout" name="inputCursorLayout">
<item>
<widget class="QGroupBox" name="hideCursorGroupBox">
<property name="title">
<string>Hide Cursor</string>
</property>
<layout class="QVBoxLayout" name="hideCursorLayout">
<item>
<widget class="QComboBox" name="hideCursorComboBox"/>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QGroupBox" name="idleTimeoutGroupBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>85</height>
</size>
</property>
<property name="title">
<string>Hide Cursor Idle Timeout</string>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignTop</set>
</property>
<property name="flat">
<bool>false</bool>
</property>
<layout class="QHBoxLayout" name="IdleTimeoutLayout" stretch="0,0">
<property name="leftMargin">
<number>70</number>
</property>
<property name="topMargin">
<number>11</number>
</property>
<item>
<widget class="QSpinBox" name="idleTimeoutSpinBox">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>80</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="layoutDirection">
<enum>Qt::LayoutDirection::LeftToRight</enum>
</property>
<property name="wrapping">
<bool>false</bool>
</property>
<property name="alignment">
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
<property name="buttonSymbols">
<enum>QAbstractSpinBox::ButtonSymbols::UpDownArrows</enum>
</property>
<property name="suffix">
<string notr="true"/>
</property>
<property name="maximum">
<number>3600</number>
</property>
<property name="value">
<number>5</number>
</property>
<property name="displayIntegerBase">
<number>10</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="idleTimeoutDurationLabel">
<property name="text">
<string>s</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="emptyTabLayoutMiddle">
<item>
<spacer name="emptyHorizontalSpacerMiddle">
<property name="orientation"> <property name="orientation">
<enum>Qt::Orientation::Horizontal</enum> <enum>Qt::Orientation::Horizontal</enum>
</property> </property>
<property name="sizeType"> <property name="sizeHint" stdset="0">
<enum>QSizePolicy::Policy::Expanding</enum> <size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
<item>
<layout class="QVBoxLayout" name="emptyTabLayoutRight">
<item>
<spacer name="emptyHorizontalSpacerRight">
<property name="orientation">
<enum>Qt::Orientation::Horizontal</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>0</width> <width>40</width>
<height>0</height> <height>20</height>
</size>
</property>
</spacer>
</item>
</layout>
</item>
</layout>
</item>
<item>
<layout class="QHBoxLayout" name="inputTabHLayoutBottom">
<property name="topMargin">
<number>0</number>
</property>
<item>
<spacer name="emptyVerticalSpacerBottom">
<property name="orientation">
<enum>Qt::Orientation::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Policy::MinimumExpanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size> </size>
</property> </property>
</spacer> </spacer>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>تمكين وحدة معالجة الرسومات الفارغة</translation> <translation>تمكين وحدة معالجة الرسومات الفارغة</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>PM4 تمكين تفريغ</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>تمكين GPU الافتراضية:\nلأغراض تصحيح الأخطاء التقنية، يقوم بتعطيل عرض اللعبة كما لو لم يكن هناك بطاقة رسومات.</translation> <translation>تمكين GPU الافتراضية:\nلأغراض تصحيح الأخطاء التقنية، يقوم بتعطيل عرض اللعبة كما لو لم يكن هناك بطاقة رسومات.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>تمكين تفريغ PM4:\nلأغراض تصحيح الأخطاء التقنية، يحفظ بيانات تعليمات GPU الأولية في مجلد أثناء معالجتها.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Aktiver virtuel GPU:\nTil teknisk fejlfinding deaktiverer det spilvisning, som om der ikke var et grafikkort.</translation> <translation>Aktiver virtuel GPU:\nTil teknisk fejlfinding deaktiverer det spilvisning, som om der ikke var et grafikkort.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Aktiver dumping af PM4:\nTil teknisk fejlfinding gemmer det GPU-kommandoer i en mappe under behandling.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>NULL GPU aktivieren</translation> <translation>NULL GPU aktivieren</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>PM4-Dumping aktivieren</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Virtuelle GPU aktivieren:\nFür das technische Debugging deaktiviert es die Spielanzeige, als ob keine Grafikkarte vorhanden wäre.</translation> <translation>Virtuelle GPU aktivieren:\nFür das technische Debugging deaktiviert es die Spielanzeige, als ob keine Grafikkarte vorhanden wäre.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>PM4-Dumping aktivieren:\nZum technischen Debuggen speichert es rohe GPU-Befehlsdaten in einem Ordner während der Verarbeitung.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Ενεργοποίηση Εικονικής GPU:\ια τεχνικό εντοπισμό σφαλμάτων, απενεργοποιεί την εμφάνιση του παιχνιδιού σαν να μην υπάρχει κάρτα γραφικών.</translation> <translation>Ενεργοποίηση Εικονικής GPU:\ια τεχνικό εντοπισμό σφαλμάτων, απενεργοποιεί την εμφάνιση του παιχνιδιού σαν να μην υπάρχει κάρτα γραφικών.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Ενεργοποίηση Καταγραφής PM4:\ια τεχνικό εντοπισμό σφαλμάτων, αποθηκεύει τις ακατέργαστες εντολές της GPU σε φάκελο κατά την επεξεργασία.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -539,6 +534,16 @@
<source>Volume</source> <source>Volume</source>
<translation>Volume</translation> <translation>Volume</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="455"/>
<source>Controller Settings</source>
<translation>Controller Settings</translation>
</message>
<message>
<location filename="../settings_dialog.ui" line="467"/>
<source>Back Button Behavior</source>
<translation>Back Button Behavior</translation>
</message>
</context> </context>
<context> <context>
<name>MainWindow</name> <name>MainWindow</name>
@ -1028,6 +1033,31 @@
<source>GUIgroupBox</source> <source>GUIgroupBox</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>
<location filename="../settings_dialog.cpp" line="330"/>
<source>backButtonBehaviorGroupBox</source>
<translation>Back Button Behavior:\nAllows setting which part of the touchpad the back button will emulate a touch on.</translation>
</message>
<message>
<location filename="../settings_dialog.cpp" line="101"/>
<source>Touchpad Left</source>
<translation>Touchpad Left</translation>
</message>
<message>
<location filename="../settings_dialog.cpp" line="102"/>
<source>Touchpad Right</source>
<translation>Touchpad Right</translation>
</message>
<message>
<location filename="../settings_dialog.cpp" line="103"/>
<source>Touchpad Center</source>
<translation>Touchpad Center</translation>
</message>
<message>
<location filename="../settings_dialog.cpp" line="104"/>
<source>None</source>
<translation>None</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="312"/> <location filename="../settings_dialog.cpp" line="312"/>
<source>graphicsAdapterGroupBox</source> <source>graphicsAdapterGroupBox</source>
@ -1053,11 +1083,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card.</translation> <translation>Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Enable PM4 Dumping:\nFor the sake of technical debugging, saves raw GPU instruction data to a folder as the emulator processes it.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Habilitar GPU NULL</translation> <translation>Habilitar GPU NULL</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Habilitar volcado de PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Habilitar GPU Nula:\nPor el bien de la depuración técnica, desactiva el renderizado del juego como si no hubiera tarjeta gráfica.</translation> <translation>Habilitar GPU Nula:\nPor el bien de la depuración técnica, desactiva el renderizado del juego como si no hubiera tarjeta gráfica.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Habilitar la Volcadura de PM4:\nPor el bien de la depuración técnica, guarda los datos de instrucciones crudas de GPU en una carpeta a medida que el emulador los procesa.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>NULL GPU فعال کردن</translation> <translation>NULL GPU فعال کردن</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>PM4 Dumping فعال کردن</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card.</translation> <translation>Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Enable PM4 Dumping:\nFor the sake of technical debugging, saves raw GPU instruction data to a folder as the emulator processes it.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Ota Null GPU käyttöön:\nTeknistä vianetsintää varten pelin renderöinti estetään niin, että ikään kuin grafiikkakorttia ei olisi.</translation> <translation>Ota Null GPU käyttöön:\nTeknistä vianetsintää varten pelin renderöinti estetään niin, että ikään kuin grafiikkakorttia ei olisi.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Ota PM4 dumpaus käyttöön:\nTeknistä vianetsintää varten raakoja GPU-ohjeita tallennetaan kansioon emulaattorin käsitellessä sitä.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>NULL GPU</translation> <translation>NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Dumper le PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Activer le GPU nul :\nPour le débogage technique, désactive le rendu du jeu comme s'il n'y avait pas de carte graphique.</translation> <translation>Activer le GPU nul :\nPour le débogage technique, désactive le rendu du jeu comme s'il n'y avait pas de carte graphique.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Activer l'exportation PM4 :\nPour le débogage technique, enregistre les données brutes des instructions GPU dans un dossier pendant que l'émulateur les traite.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>NULL GPU Engedélyezése</translation> <translation>NULL GPU Engedélyezése</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>PM4 Dumpolás Engedélyezése</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Null GPU engedélyezése:\nMűszaki hibaelhárítás céljából letiltja a játék renderelését, mintha nem lenne grafikus kártya.</translation> <translation>Null GPU engedélyezése:\nMűszaki hibaelhárítás céljából letiltja a játék renderelését, mintha nem lenne grafikus kártya.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>PM4 dumpolás engedélyezése:\nMűszaki hibaelhárítás céljából a nyers GPU utasítási adatokat elmenti egy mappába, ahogy az emulátor feldolgozza őket.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Aktifkan GPU Null:\nUntuk tujuan debugging teknis, menonaktifkan rendering permainan seolah-olah tidak ada kartu grafis.</translation> <translation>Aktifkan GPU Null:\nUntuk tujuan debugging teknis, menonaktifkan rendering permainan seolah-olah tidak ada kartu grafis.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Aktifkan Pembuangan PM4:\nUntuk tujuan debugging teknis, menyimpan data instruksi GPU mentah ke folder saat emulator memprosesnya.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Abilita NULL GPU</translation> <translation>Abilita NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Abilita Dump PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Abilita GPU Null:\nPer scopi di debug tecnico, disabilita il rendering del gioco come se non ci fosse alcuna scheda grafica.</translation> <translation>Abilita GPU Null:\nPer scopi di debug tecnico, disabilita il rendering del gioco come se non ci fosse alcuna scheda grafica.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Abilita Pompaggio PM4:\nPer scopi di debug tecnico, salva i dati delle istruzioni GPU grezze in una cartella mentre l'emulatore li elabora.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>NULL GPUを有効にする</translation> <translation>NULL GPUを有効にする</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>PM4ダンプを有効にする</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Null GPUを有効にする:\n技術的なデバッグの目的で</translation> <translation>Null GPUを有効にする:\n技術的なデバッグの目的で</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>PM4ダンプを有効にする:\n技術的なデバッグの目的でGPU命令データをフォルダーに保存します</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card.</translation> <translation>Enable Null GPU:\nFor the sake of technical debugging, disables game rendering as if there were no graphics card.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Enable PM4 Dumping:\nFor the sake of technical debugging, saves raw GPU instruction data to a folder as the emulator processes it.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Įjungti tuščią GPU:\nTechninio derinimo tikslais išjungia žaidimo renderiavimą, tarsi nebūtų grafikos plokštės.</translation> <translation>Įjungti tuščią GPU:\nTechninio derinimo tikslais išjungia žaidimo renderiavimą, tarsi nebūtų grafikos plokštės.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Įjungti PM4 išmetimą:\nTechninio derinimo tikslais saugo žalius GPU nurodymų duomenis į aplanką, kai emuliatorius juos apdoroja.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillrendering som om det ikke var noe grafikkort.</translation> <translation>Aktiver Null GPU:\nFor teknisk feilsøking deaktiverer spillrendering som om det ikke var noe grafikkort.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Aktiver PM4 dumping:\nFor teknisk feilsøking lagrer GPU-instruksjonsdata i en mappe mens emulatoren behandler dem.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Null GPU inschakelen:\nVoor technische foutopsporing schakelt de game-rendering uit alsof er geen grafische kaart is.</translation> <translation>Null GPU inschakelen:\nVoor technische foutopsporing schakelt de game-rendering uit alsof er geen grafische kaart is.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>PM4 dumpen inschakelen:\nVoor technische foutopsporing slaat het ruwe GPU-instructiegegevens op in een map terwijl de emulator ze verwerkt.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Wyłącz kartę graficzną</translation> <translation>Wyłącz kartę graficzną</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Włącz zgrywanie PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Włącz Null GPU:\nDla technicznego debugowania dezaktywuje renderowanie gry tak, jakby nie było karty graficznej.</translation> <translation>Włącz Null GPU:\nDla technicznego debugowania dezaktywuje renderowanie gry tak, jakby nie było karty graficznej.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Włącz zrzucanie PM4:\nDla technicznego debugowania zapisuje surowe dane instrukcji GPU w folderze, gdy emulator je przetwarza.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Ativar GPU NULA</translation> <translation>Ativar GPU NULA</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Ativar Dumping de PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Ativar GPU NULA:\nDesativa a renderização do jogo para fins de depuração técnica, como se não houvesse nenhuma placa gráfica.</translation> <translation>Ativar GPU NULA:\nDesativa a renderização do jogo para fins de depuração técnica, como se não houvesse nenhuma placa gráfica.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Ativar Dumping de PM4:\nArmazena os dados de instrução bruta da GPU em uma pasta enquanto o emulador os processa, para fins de depuração técnica. Recomendado deixar desativado.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Activează GPU Null:\nÎn scopuri de depanare tehnică, dezactivează redarea jocului ca și cum nu ar exista o placă grafică.</translation> <translation>Activează GPU Null:\nÎn scopuri de depanare tehnică, dezactivează redarea jocului ca și cum nu ar exista o placă grafică.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Activează salvarea PM4:\nÎn scopuri de depanare tehnică, salvează datele brute ale instrucțiunilor GPU într-un folder pe măsură ce emulatorul le procesează.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Включить NULL GPU</translation> <translation>Включить NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Включить дамп PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Включить NULL GPU:\nДля технической отладки отключает рендеринг игры так, как будто графической карты нет.</translation> <translation>Включить NULL GPU:\nДля технической отладки отключает рендеринг игры так, как будто графической карты нет.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Включить дамп PM4:\nДля технической отладки сохраняет необработанные данные инструкций GPU в папку, пока эмулятор их обрабатывает.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -417,7 +417,7 @@
<message> <message>
<location filename="../settings_dialog.ui" line="155"/> <location filename="../settings_dialog.ui" line="155"/>
<source>Username</source> <source>Username</source>
<translation>Nofka</translation> <translation>Përdoruesi</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.ui" line="178"/> <location filename="../settings_dialog.ui" line="178"/>
@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Aktivizo GPU- NULL</translation> <translation>Aktivizo GPU- NULL</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Aktivizo Zbrazjen PM4</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -517,7 +512,7 @@
<message> <message>
<location filename="../settings_dialog.ui" line="313"/> <location filename="../settings_dialog.ui" line="313"/>
<source>Update Channel</source> <source>Update Channel</source>
<translation>Kanali i Përditësimit</translation> <translation>Kanali i përditësimit</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.ui" line="322"/> <location filename="../settings_dialog.ui" line="322"/>
@ -527,7 +522,7 @@
<message> <message>
<location filename="../settings_dialog.ui" line="354"/> <location filename="../settings_dialog.ui" line="354"/>
<source>GUI Settings</source> <source>GUI Settings</source>
<translation>Parametrat e GUI</translation> <translation>Cilësimet e GUI</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.ui" line="375"/> <location filename="../settings_dialog.ui" line="375"/>
@ -537,7 +532,7 @@
<message> <message>
<location filename="../settings_dialog.ui" line="394"/> <location filename="../settings_dialog.ui" line="394"/>
<source>Volume</source> <source>Volume</source>
<translation>Volumi</translation> <translation>Vëllimi i zërit</translation>
</message> </message>
</context> </context>
<context> <context>
@ -976,12 +971,12 @@
<message> <message>
<location filename="../settings_dialog.cpp" line="72"/> <location filename="../settings_dialog.cpp" line="72"/>
<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>Hidhni mouse-in mbi një opsion për shfaqur përshkrimin e tij.</translation> <translation>Vendos miun mbi një rregullim për shfaqur përshkrimin e tij.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="289"/> <location filename="../settings_dialog.cpp" line="289"/>
<source>consoleLanguageGroupBox</source> <source>consoleLanguageGroupBox</source>
<translation>Gjuha e konsolës:\nPërcakton gjuhën përdor loja PS4.\nRrekomandohet vendosni këtë një gjuhë loja mbështet, e cila do ndryshojë sipas rajonit.</translation> <translation>Gjuha e konsolës:\nPërcakton gjuhën përdor loja PS4.\nKëshillohet caktosh një gjuhë loja mbështet, e cila do ndryshojë sipas rajonit.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="291"/> <location filename="../settings_dialog.cpp" line="291"/>
@ -991,17 +986,17 @@
<message> <message>
<location filename="../settings_dialog.cpp" line="293"/> <location filename="../settings_dialog.cpp" line="293"/>
<source>fullscreenCheckBox</source> <source>fullscreenCheckBox</source>
<translation>Aktivizo ekranin e plotë:\nAutomatikisht vendos dritaren e lojës modalitetin e ekranit plotë.\nKjo mund aktivizohet duke shtypur çelësin F11.</translation> <translation>Aktivizo ekranin e plotë:\nVendos automatikisht dritaren e lojës mënyrën e ekranit plotë.\nKjo mund aktivizohet duke shtypur tastin F11.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="295"/> <location filename="../settings_dialog.cpp" line="295"/>
<source>showSplashCheckBox</source> <source>showSplashCheckBox</source>
<translation>Shfaq ekranin e ngarkesës:\nShfaq ekranin e ngarkesës lojës (një imazh special) gjatë fillimit lojës.</translation> <translation>Shfaq ekranin e ngarkesës:\nShfaq ekranin e ngarkesës lojës (një pamje e veçantë) gjatë fillimit lojës.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="297"/> <location filename="../settings_dialog.cpp" line="297"/>
<source>ps4proCheckBox</source> <source>ps4proCheckBox</source>
<translation>Është PS4 Pro:\nBën emulatori veprojë si një PS4 PRO, i cili mund aktivizojë karakteristika speciale lojrat e mbështesin atë.</translation> <translation>Është PS4 Pro:\nBën emulatori veprojë si një PS4 PRO, gjë mund aktivizojë veçori veçanta lojrat e mbështesin.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="299"/> <location filename="../settings_dialog.cpp" line="299"/>
@ -1011,72 +1006,67 @@
<message> <message>
<location filename="../settings_dialog.cpp" line="301"/> <location filename="../settings_dialog.cpp" line="301"/>
<source>logTypeGroupBox</source> <source>logTypeGroupBox</source>
<translation>Tipi i logut:\nPërcakton nëse sinkronizoni daljen e dritares logut për performancën. Mund ketë efekte këqija emulim.</translation> <translation>Lloji i ditarit:\nPërcakton nëse sinkronizohet dalja e dritares ditarit për performancë. Mund ketë efekte këqija emulim.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="303"/> <location filename="../settings_dialog.cpp" line="303"/>
<source>logFilter</source> <source>logFilter</source>
<translation>Filtri i logut: Filtron logun për printuar vetëm informacione specifike. Shembuj: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivelet: Trace, Debug, Info, Warning, Error, Critical - këtë rend, një nivel specifik hesht gjitha nivelet përpara listë dhe regjistron çdo nivel pas saj.</translation> <translation>Filtri i ditarit: Filtron ditarin për shfaqur vetëm informacione specifike. Shembuj: "Core:Trace" "Lib.Pad:Debug Common.Filesystem:Error" "*:Critical" Nivelet: Trace, Debug, Info, Warning, Error, Critical - këtë rend, një nivel specifik hesht gjitha nivelet përpara listë dhe regjistron çdo nivel pas atij.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="305"/> <location filename="../settings_dialog.cpp" line="305"/>
<source>updaterGroupBox</source> <source>updaterGroupBox</source>
<translation>Aktualizimi:\nRelease: Versionet zyrtare lëshuara çdo muaj mund jenë shumë vjetra, por janë besueshme dhe testuara.\nNightly: Versionet e zhvillimit kanë gjitha veçoritë dhe rregullimet fundit, por mund përmbajnë gabime dhe janë pak qëndrueshme.</translation> <translation>Aktualizimi:\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>
<location filename="../settings_dialog.cpp" line="306"/> <location filename="../settings_dialog.cpp" line="306"/>
<source>GUIgroupBox</source> <source>GUIgroupBox</source>
<translation>Lojë muzikë titulli:\nNëse një lojë e mbështet, aktivizoja luajtjen e muzikës speciale kur zgjidhni 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>
<location filename="../settings_dialog.cpp" line="312"/> <location filename="../settings_dialog.cpp" line="312"/>
<source>graphicsAdapterGroupBox</source> <source>graphicsAdapterGroupBox</source>
<translation>Dispositivi grafik:\nNë sistemet me GPU shumëfishta, zgjidhni GPU- do përdorë emulatori nga lista e rënies,\nor zgjidhni "Auto Select" për ta përcaktuar automatikisht.</translation> <translation>Pajisja grafike:\nNë sistemet me GPU shumëfishta, zgjidh GPU- do përdorë emulatori nga lista rënëse,\nose zgjidh "Auto Select" për ta përcaktuar automatikisht.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="314"/> <location filename="../settings_dialog.cpp" line="314"/>
<source>resolutionLayout</source> <source>resolutionLayout</source>
<translation>Gjerësia/ Lartësia:\nPërcakton madhësinë e dritares emulatorit nisje, e cila mund rregullohet gjatë lojës.\nKjo është ndryshe nga rezolucioni lojë.</translation> <translation>Gjerësia/Lartësia:\nPërcakton madhësinë e dritares emulatorit nisje, e cila mund rregullohet gjatë lojës.\nKjo është ndryshe nga rezolucioni lojë.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="318"/> <location filename="../settings_dialog.cpp" line="318"/>
<source>heightDivider</source> <source>heightDivider</source>
<translation>Pjesëtari Vblank:\nShpejtësia e kuadrit me cilën refreshohet emulatori është shumëzuar me këtë numër. Ndryshimi i këtij mund ketë efekte këqija, si rritja e shpejtësisë lojës ose shkatërrimi i funksionalitetit kritik lojës nuk e pret këtë ndryshojë!</translation> <translation>Ndarësi Vblank:\nFrekuenca pamore me cilën rifreskohet emulatori shumëzohet me këtë numër. Ndryshimi i këtij mund ketë efekte këqija, si rritja e shpejtësisë lojës ose prishja e punimit thelbësor lojës nuk e pret këtë ndryshim!</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="320"/> <location filename="../settings_dialog.cpp" line="320"/>
<source>dumpShadersCheckBox</source> <source>dumpShadersCheckBox</source>
<translation>Aktivizo dump-in e shaders:\nPër qëllime debugimit teknik, ruan shaders e lojës një folder ndërsa ato renditen.</translation> <translation>Aktivizo zbrazjen e shaders-ave:\nPër qëllime korrigjimit teknik, ruan shaders-at e lojës një dosje ndërsa ato pasqyrohen.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="322"/> <location filename="../settings_dialog.cpp" line="322"/>
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Aktivizo GPU Null:\nPër qëllime debugimit teknik, deaktivizon renditjen e lojës sikur nuk do kishte një kartë grafike.</translation> <translation>Aktivizo GPU- Null:\nPër qëllime korrigjimit teknik, çaktivizon pasqyrimin e lojës sikur nuk ka një kartë grafike.</translation>
</message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Aktivizo dump-in e PM4:\nPër qëllime debugimit teknik, ruan dhënat e instruksioneve GPU- një folder ndërsa emulatori i përpunon ato.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>
<translation>Aktivizo dump-in e debugimit:\nRuani simbolet e importit dhe eksportit dhe informacionin e titullit skedarit për aplikacionin aktual PS4 po punon një katalog.</translation> <translation>Aktivizo zbrazjen për korrigjim:\nRuan simbolet e importit dhe eksportit dhe informacionin e kreut skedarit për aplikacionin PS4 po ekzekutohet një dosje.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="331"/> <location filename="../settings_dialog.cpp" line="331"/>
<source>vkValidationCheckBox</source> <source>vkValidationCheckBox</source>
<translation>Aktivizo stratet e validimit Vulkan:\nAktivizon një sistem validon gjendjen e renderizuesit Vulkan dhe regjistron informacionin lidhje me gjendjen e tij brendshme. Kjo do ulet performancën dhe ndoshta do ndryshojë sjelljen e emulimit.</translation> <translation>Aktivizo shtresat e vlefshmërisë Vulkan:\nAktivizon një sistem vërteton gjendjen e pasqyruesit Vulkan dhe regjistron informacionin lidhje me gjendjen e tij brendshme. Kjo do ul performancën dhe ndoshta do ndryshojë sjelljen e emulimit.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="333"/> <location filename="../settings_dialog.cpp" line="333"/>
<source>vkSyncValidationCheckBox</source> <source>vkSyncValidationCheckBox</source>
<translation>Aktivizo validimin e sinkronizimit Vulkan:\nAktivizon një sistem validon kohën e detyrave renderizimit Vulkan. Kjo do ulet performancën dhe ndoshta do ndryshojë sjelljen e emulimit.</translation> <translation>Aktivizo vërtetimin e sinkronizimit Vulkan:\nAktivizon një sistem vërteton kohën e detyrave pasqyrimit Vulkan. Kjo do ul performancën dhe ndoshta do ndryshojë sjelljen e emulimit.</translation>
</message> </message>
<message> <message>
<location filename="../settings_dialog.cpp" line="335"/> <location filename="../settings_dialog.cpp" line="335"/>
<source>rdocCheckBox</source> <source>rdocCheckBox</source>
<translation>Aktivizo debugimin RenderDoc:\nNëse aktivizohet, emulatori do ofrojë pajtueshmëri me Renderdoc për lejuar kapjen dhe analizën e kornizës aktuale renderizuar.</translation> <translation>Aktivizo korrigjimin RenderDoc:\nNëse aktivizohet, emulatori do ofrojë pajtueshmëri me Renderdoc për lejuar kapjen dhe analizën e pamjes pasqyruar moment.</translation>
</message> </message>
</context> </context>
<context> <context>
@ -1172,7 +1162,7 @@
<message> <message>
<location filename="../check_update.cpp" line="187"/> <location filename="../check_update.cpp" line="187"/>
<source>Update Channel</source> <source>Update Channel</source>
<translation>Kanali i Përditësimit</translation> <translation>Kanali i përditësimit</translation>
</message> </message>
<message> <message>
<location filename="../check_update.cpp" line="177"/> <location filename="../check_update.cpp" line="177"/>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>NULL GPU'yu Etkinleştir</translation> <translation>NULL GPU'yu Etkinleştir</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>PM4 Kaydını Etkinleştir</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Null GPU'yu Etkinleştir:\nTeknik hata ayıklama amacıyla, oyunun render edilmesini grafik kartı yokmuş gibi devre dışı bırakır.</translation> <translation>Null GPU'yu Etkinleştir:\nTeknik hata ayıklama amacıyla, oyunun render edilmesini grafik kartı yokmuş gibi devre dışı bırakır.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>PM4 Dışa Aktarmayı Etkinleştir:\nTeknik hata ayıklama amacıyla, emülatör bunları işlerken GPU komut verilerini bir klasöre kaydeder.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>Bật GPU Null:\nĐể mục đích gỡ lỗi kỹ thuật, hiệu hóa việc kết xuất trò chơi như thể không card đ họa.</translation> <translation>Bật GPU Null:\nĐể mục đích gỡ lỗi kỹ thuật, hiệu hóa việc kết xuất trò chơi như thể không card đ họa.</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>Bật xuất PM4:\nĐể mục đích gỡ lỗi kỹ thuật, lưu dữ liệu lệnh GPU vào một thư mục khi trình giả lập xử chúng.</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation> NULL GPU</translation> <translation> NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation> PM4 </translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation> GPU:\n为了技术调试仿</translation> <translation> GPU:\n为了技术调试仿</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation> PM4 :\n为了技术调试 GPU </translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -474,11 +474,6 @@
<source>Enable NULL GPU</source> <source>Enable NULL GPU</source>
<translation>Enable NULL GPU</translation> <translation>Enable NULL GPU</translation>
</message> </message>
<message>
<location filename="../settings_dialog.ui" line="476"/>
<source>Enable PM4 Dumping</source>
<translation>Enable PM4 Dumping</translation>
</message>
<message> <message>
<location filename="../settings_dialog.ui" line="517"/> <location filename="../settings_dialog.ui" line="517"/>
<source>Debug</source> <source>Debug</source>
@ -1053,11 +1048,6 @@
<source>nullGpuCheckBox</source> <source>nullGpuCheckBox</source>
<translation>GPU:\n為了技術調試彿</translation> <translation>GPU:\n為了技術調試彿</translation>
</message> </message>
<message>
<location filename="../settings_dialog.cpp" line="323"/>
<source>dumpPM4CheckBox</source>
<translation>PM4轉儲:\n為了技術調試GPU指令數據在模擬器處理時保存到文件夾中</translation>
</message>
<message> <message>
<location filename="../settings_dialog.cpp" line="329"/> <location filename="../settings_dialog.cpp" line="329"/>
<source>debugDump</source> <source>debugDump</source>

View File

@ -145,6 +145,7 @@ void WindowSDL::onKeyPress(const SDL_Event* event) {
Input::Axis axis = Input::Axis::AxisMax; Input::Axis axis = Input::Axis::AxisMax;
int axisvalue = 0; int axisvalue = 0;
int ax = 0; int ax = 0;
std::string backButtonBehavior = Config::getBackButtonBehavior();
switch (event->key.key) { switch (event->key.key) {
case SDLK_UP: case SDLK_UP:
button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP; button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_UP;
@ -278,7 +279,15 @@ void WindowSDL::onKeyPress(const SDL_Event* event) {
ax = Input::GetAxis(0, 0x80, axisvalue); ax = Input::GetAxis(0, 0x80, axisvalue);
break; break;
case SDLK_SPACE: case SDLK_SPACE:
if (backButtonBehavior != "none") {
float x = backButtonBehavior == "left" ? 0.25f
: (backButtonBehavior == "right" ? 0.75f : 0.5f);
// trigger a touchpad event so that the touchpad emulation for back button works
controller->SetTouchpadState(0, true, x, 0.5f);
button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD; button = OrbisPadButtonDataOffset::ORBIS_PAD_BUTTON_TOUCH_PAD;
} else {
button = 0;
}
break; break;
case SDLK_F11: case SDLK_F11:
if (event->type == SDL_EVENT_KEY_DOWN) { if (event->type == SDL_EVENT_KEY_DOWN) {
@ -304,9 +313,6 @@ void WindowSDL::onKeyPress(const SDL_Event* event) {
if (axis != Input::Axis::AxisMax) { if (axis != Input::Axis::AxisMax) {
controller->Axis(0, axis, ax); controller->Axis(0, axis, ax);
} }
if (SDL_GetCursor() != NULL) {
SDL_HideCursor();
}
} }
void WindowSDL::onGamepadEvent(const SDL_Event* event) { void WindowSDL::onGamepadEvent(const SDL_Event* event) {
@ -330,10 +336,20 @@ void WindowSDL::onGamepadEvent(const SDL_Event* event) {
case SDL_EVENT_GAMEPAD_BUTTON_UP: case SDL_EVENT_GAMEPAD_BUTTON_UP:
button = sdlGamepadToOrbisButton(event->gbutton.button); button = sdlGamepadToOrbisButton(event->gbutton.button);
if (button != 0) { if (button != 0) {
if (event->gbutton.button == SDL_GAMEPAD_BUTTON_BACK) {
std::string backButtonBehavior = Config::getBackButtonBehavior();
if (backButtonBehavior != "none") {
float x = backButtonBehavior == "left"
? 0.25f
: (backButtonBehavior == "right" ? 0.75f : 0.5f);
// trigger a touchpad event so that the touchpad emulation for back button works
controller->SetTouchpadState(0, true, x, 0.5f);
controller->CheckButton(0, button,
event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
}
} else {
controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN); controller->CheckButton(0, button, event->type == SDL_EVENT_GAMEPAD_BUTTON_DOWN);
} }
if (SDL_GetCursor() != NULL) {
SDL_HideCursor();
} }
break; break;
case SDL_EVENT_GAMEPAD_AXIS_MOTION: case SDL_EVENT_GAMEPAD_AXIS_MOTION:

View File

@ -27,8 +27,10 @@ static constexpr spv::ExecutionMode GetInputPrimitiveType(AmdGpu::PrimitiveType
case AmdGpu::PrimitiveType::TriangleList: case AmdGpu::PrimitiveType::TriangleList:
case AmdGpu::PrimitiveType::TriangleStrip: case AmdGpu::PrimitiveType::TriangleStrip:
return spv::ExecutionMode::Triangles; return spv::ExecutionMode::Triangles;
case AmdGpu::PrimitiveType::AdjTriangleList:
return spv::ExecutionMode::InputTrianglesAdjacency;
default: default:
UNREACHABLE(); UNREACHABLE_MSG("Unknown input primitive type {}", u32(type));
} }
} }
@ -41,7 +43,7 @@ static constexpr spv::ExecutionMode GetOutputPrimitiveType(AmdGpu::GsOutputPrimi
case AmdGpu::GsOutputPrimitiveType::TriangleStrip: case AmdGpu::GsOutputPrimitiveType::TriangleStrip:
return spv::ExecutionMode::OutputTriangleStrip; return spv::ExecutionMode::OutputTriangleStrip;
default: default:
UNREACHABLE(); UNREACHABLE_MSG("Unknown output primitive type {}", u32(type));
} }
} }
@ -68,6 +70,8 @@ ArgType Arg(EmitContext& ctx, const IR::Value& arg) {
return arg.ScalarReg(); return arg.ScalarReg();
} else if constexpr (std::is_same_v<ArgType, IR::VectorReg>) { } else if constexpr (std::is_same_v<ArgType, IR::VectorReg>) {
return arg.VectorReg(); return arg.VectorReg();
} else if constexpr (std::is_same_v<ArgType, const char*>) {
return arg.StringLiteral();
} }
} }

View File

@ -48,6 +48,7 @@ void EmitPrologue(EmitContext& ctx);
void EmitEpilogue(EmitContext& ctx); void EmitEpilogue(EmitContext& ctx);
void EmitDiscard(EmitContext& ctx); void EmitDiscard(EmitContext& ctx);
void EmitDiscardCond(EmitContext& ctx, Id condition); void EmitDiscardCond(EmitContext& ctx, Id condition);
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id arg0, Id arg1, Id arg2, Id arg3, Id arg4);
void EmitBarrier(EmitContext& ctx); void EmitBarrier(EmitContext& ctx);
void EmitWorkgroupMemoryBarrier(EmitContext& ctx); void EmitWorkgroupMemoryBarrier(EmitContext& ctx);
void EmitDeviceMemoryBarrier(EmitContext& ctx); void EmitDeviceMemoryBarrier(EmitContext& ctx);

View File

@ -3,6 +3,7 @@
#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h" #include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
#include "shader_recompiler/backend/spirv/spirv_emit_context.h" #include "shader_recompiler/backend/spirv/spirv_emit_context.h"
#include "shader_recompiler/ir/debug_print.h"
namespace Shader::Backend::SPIRV { namespace Shader::Backend::SPIRV {
@ -57,4 +58,11 @@ void EmitEndPrimitive(EmitContext& ctx, const IR::Value& stream) {
throw NotImplementedException("Geometry streams"); throw NotImplementedException("Geometry streams");
} }
void EmitDebugPrint(EmitContext& ctx, IR::Inst* inst, Id fmt, Id arg0, Id arg1, Id arg2, Id arg3) {
IR::DebugPrintFlags flags = inst->Flags<IR::DebugPrintFlags>();
std::array<Id, IR::DEBUGPRINT_NUM_FORMAT_ARGS> fmt_args = {arg0, arg1, arg2, arg3};
auto fmt_args_span = std::span<Id>(fmt_args.begin(), fmt_args.begin() + flags.num_args);
ctx.OpDebugPrintf(fmt, fmt_args_span);
}
} // namespace Shader::Backend::SPIRV } // namespace Shader::Backend::SPIRV

View File

@ -34,14 +34,17 @@ std::string_view StageName(Stage stage) {
throw InvalidArgument("Invalid stage {}", u32(stage)); throw InvalidArgument("Invalid stage {}", u32(stage));
} }
static constexpr u32 NumVertices(AmdGpu::GsOutputPrimitiveType type) { static constexpr u32 NumVertices(AmdGpu::PrimitiveType type) {
switch (type) { switch (type) {
case AmdGpu::GsOutputPrimitiveType::PointList: case AmdGpu::PrimitiveType::PointList:
return 1u; return 1u;
case AmdGpu::GsOutputPrimitiveType::LineStrip: case AmdGpu::PrimitiveType::LineList:
return 2u; return 2u;
case AmdGpu::GsOutputPrimitiveType::TriangleStrip: case AmdGpu::PrimitiveType::TriangleList:
case AmdGpu::PrimitiveType::TriangleStrip:
return 3u; return 3u;
case AmdGpu::PrimitiveType::AdjTriangleList:
return 6u;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
@ -88,6 +91,8 @@ Id EmitContext::Def(const IR::Value& value) {
return ConstF32(value.F32()); return ConstF32(value.F32());
case IR::Type::F64: case IR::Type::F64:
return Constant(F64[1], value.F64()); return Constant(F64[1], value.F64());
case IR::Type::StringLiteral:
return String(value.StringLiteral());
default: default:
throw NotImplementedException("Immediate type {}", value.Type()); throw NotImplementedException("Immediate type {}", value.Type());
} }
@ -321,16 +326,15 @@ void EmitContext::DefineInputs() {
MemberDecorate(gl_per_vertex, 2, spv::Decoration::BuiltIn, MemberDecorate(gl_per_vertex, 2, spv::Decoration::BuiltIn,
static_cast<std::uint32_t>(spv::BuiltIn::ClipDistance)); static_cast<std::uint32_t>(spv::BuiltIn::ClipDistance));
Decorate(gl_per_vertex, spv::Decoration::Block); Decorate(gl_per_vertex, spv::Decoration::Block);
const auto vertices_in = const auto num_verts_in = NumVertices(runtime_info.gs_info.in_primitive);
TypeArray(gl_per_vertex, ConstU32(NumVertices(runtime_info.gs_info.out_primitive[0]))); const auto vertices_in = TypeArray(gl_per_vertex, ConstU32(num_verts_in));
gl_in = Name(DefineVar(vertices_in, spv::StorageClass::Input), "gl_in"); gl_in = Name(DefineVar(vertices_in, spv::StorageClass::Input), "gl_in");
interfaces.push_back(gl_in); interfaces.push_back(gl_in);
const auto num_params = runtime_info.gs_info.in_vertex_data_size / 4 - 1u; const auto num_params = runtime_info.gs_info.in_vertex_data_size / 4 - 1u;
for (int param_id = 0; param_id < num_params; ++param_id) { for (int param_id = 0; param_id < num_params; ++param_id) {
const IR::Attribute param{IR::Attribute::Param0 + param_id}; const IR::Attribute param{IR::Attribute::Param0 + param_id};
const Id type{ const Id type{TypeArray(F32[4], ConstU32(num_verts_in))};
TypeArray(F32[4], ConstU32(NumVertices(runtime_info.gs_info.out_primitive[0])))};
const Id id{DefineInput(type, param_id)}; const Id id{DefineInput(type, param_id)};
Name(id, fmt::format("in_attr{}", param_id)); Name(id, fmt::format("in_attr{}", param_id));
input_params[param_id] = {id, input_f32, F32[1], 4}; input_params[param_id] = {id, input_f32, F32[1], 4};

View File

@ -15,18 +15,18 @@ CopyShaderData ParseCopyShader(const std::span<const u32>& code) {
ASSERT_MSG(code[0] == token_mov_vcchi, "First instruction is not s_mov_b32 vcc_hi, #imm"); ASSERT_MSG(code[0] == token_mov_vcchi, "First instruction is not s_mov_b32 vcc_hi, #imm");
std::array<s32, 32> offsets{}; std::array<s32, 32> offsets{};
std::fill(offsets.begin(), offsets.end(), -1); offsets.fill(-1);
std::array<s32, 256> sources{};
sources.fill(-1);
CopyShaderData data{}; CopyShaderData data{};
Gcn::OperandField sgpr{};
auto last_attr{IR::Attribute::Position0}; auto last_attr{IR::Attribute::Position0};
s32 soffset{0};
while (!code_slice.atEnd()) { while (!code_slice.atEnd()) {
auto inst = decoder.decodeInstruction(code_slice); auto inst = decoder.decodeInstruction(code_slice);
switch (inst.opcode) { switch (inst.opcode) {
case Gcn::Opcode::S_MOVK_I32: { case Gcn::Opcode::S_MOVK_I32: {
sgpr = inst.dst[0].field; sources[inst.dst[0].code] = inst.control.sopk.simm;
soffset = inst.control.sopk.simm;
break; break;
} }
case Gcn::Opcode::EXP: { case Gcn::Opcode::EXP: {
@ -46,8 +46,9 @@ CopyShaderData ParseCopyShader(const std::span<const u32>& code) {
case Gcn::Opcode::BUFFER_LOAD_DWORD: { case Gcn::Opcode::BUFFER_LOAD_DWORD: {
offsets[inst.src[1].code] = inst.control.mubuf.offset; offsets[inst.src[1].code] = inst.control.mubuf.offset;
if (inst.src[3].field != Gcn::OperandField::ConstZero) { if (inst.src[3].field != Gcn::OperandField::ConstZero) {
ASSERT(inst.src[3].field == sgpr); const u32 index = inst.src[3].code;
offsets[inst.src[1].code] += soffset; ASSERT(sources[index] != -1);
offsets[inst.src[1].code] += sources[index];
} }
break; break;
} }
@ -59,6 +60,7 @@ CopyShaderData ParseCopyShader(const std::span<const u32>& code) {
if (last_attr != IR::Attribute::Position0) { if (last_attr != IR::Attribute::Position0) {
data.num_attrs = static_cast<u32>(last_attr) - static_cast<u32>(IR::Attribute::Param0) + 1; data.num_attrs = static_cast<u32>(last_attr) - static_cast<u32>(IR::Attribute::Param0) + 1;
} }
return data; return data;
} }

View File

@ -3642,8 +3642,8 @@ constexpr std::array<InstFormat, 112> InstructionFormatMIMG = {{
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined,
ScalarType::Undefined}, ScalarType::Undefined},
// 95 = IMAGE_GATHER4_C_LZ_O // 95 = IMAGE_GATHER4_C_LZ_O
{InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Undefined, {InstClass::VectorMemImgSmp, InstCategory::VectorMemory, 4, 1, ScalarType::Uint32,
ScalarType::Undefined}, ScalarType::Float32},
// 96 = IMAGE_GET_LOD // 96 = IMAGE_GET_LOD
{InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Float32, {InstClass::VectorMemImgUt, InstCategory::VectorMemory, 4, 1, ScalarType::Float32,
ScalarType::Float32}, ScalarType::Float32},

View File

@ -147,6 +147,7 @@ void Translator::EmitVectorMemory(const GcnInst& inst) {
case Opcode::IMAGE_GATHER4_C_O: case Opcode::IMAGE_GATHER4_C_O:
case Opcode::IMAGE_GATHER4_C_LZ: case Opcode::IMAGE_GATHER4_C_LZ:
case Opcode::IMAGE_GATHER4_LZ_O: case Opcode::IMAGE_GATHER4_LZ_O:
case Opcode::IMAGE_GATHER4_C_LZ_O:
return IMAGE_GATHER(inst); return IMAGE_GATHER(inst);
// Image misc operations // Image misc operations

View File

@ -3,6 +3,7 @@
#pragma once #pragma once
#include <span> #include <span>
#include <vector>
#include <boost/container/small_vector.hpp> #include <boost/container/small_vector.hpp>
#include <boost/container/static_vector.hpp> #include <boost/container/static_vector.hpp>
#include "common/assert.h" #include "common/assert.h"

View File

@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "common/bit_field.h"
#include "shader_recompiler/ir/opcodes.h"
#include "src/common/types.h"
#pragma once
namespace Shader::IR {
constexpr size_t DEBUGPRINT_NUM_FORMAT_ARGS = NumArgsOf(IR::Opcode::DebugPrint) - 1;
union DebugPrintFlags {
u32 raw;
// For now, only flag is the number of variadic format args actually used
// So bitfield not really needed
BitField<0, 32, u32> num_args;
};
} // namespace Shader::IR

View File

@ -1,10 +1,15 @@
// 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 <array>
#include <bit> #include <bit>
#include <source_location> #include <source_location>
#include <boost/container/small_vector.hpp>
#include "common/assert.h"
#include "shader_recompiler/exception.h" #include "shader_recompiler/exception.h"
#include "shader_recompiler/ir/debug_print.h"
#include "shader_recompiler/ir/ir_emitter.h" #include "shader_recompiler/ir/ir_emitter.h"
#include "shader_recompiler/ir/opcodes.h"
#include "shader_recompiler/ir/value.h" #include "shader_recompiler/ir/value.h"
namespace Shader::IR { namespace Shader::IR {
@ -1553,6 +1558,38 @@ void IREmitter::ImageWrite(const Value& handle, const Value& coords, const Value
Inst(Opcode::ImageWrite, Flags{info}, handle, coords, color); Inst(Opcode::ImageWrite, Flags{info}, handle, coords, color);
} }
// Debug print maps to SPIRV's NonSemantic DebugPrintf instruction
// Renderdoc will hook in its own implementation of the SPIRV instruction
// Renderdoc accepts format specifiers, e.g. %u, listed here:
// https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/main/docs/debug_printf.md
//
// fmt must be a string literal (pointer is shallow copied into a Value)
// Example usage:
// ir.DebugPrint("invocation xyz: (%u, %u, %u)",
// {ir.GetVectorReg(IR::VectorReg::V0),
// ir.GetVectorReg(IR::VectorReg::V1),
// ir.GetVectorReg(IR::VectorReg::V2)});
void IREmitter::DebugPrint(const char* fmt, boost::container::small_vector<Value, 5> format_args) {
std::array<Value, DEBUGPRINT_NUM_FORMAT_ARGS> args;
ASSERT_MSG(format_args.size() < DEBUGPRINT_NUM_FORMAT_ARGS,
"DebugPrint only supports up to {} format args", DEBUGPRINT_NUM_FORMAT_ARGS);
for (int i = 0; i < format_args.size(); i++) {
args[i] = format_args[i];
}
for (int i = format_args.size(); i < DEBUGPRINT_NUM_FORMAT_ARGS; i++) {
args[i] = Inst(Opcode::Void);
}
IR::Value fmt_val{fmt};
DebugPrintFlags flags;
flags.num_args.Assign(format_args.size());
Inst(Opcode::DebugPrint, Flags{flags}, fmt_val, args[0], args[1], args[2], args[3]);
}
void IREmitter::EmitVertex() { void IREmitter::EmitVertex() {
Inst(Opcode::EmitVertex); Inst(Opcode::EmitVertex);
} }

View File

@ -6,6 +6,7 @@
#include <cstring> #include <cstring>
#include <type_traits> #include <type_traits>
#include "shader_recompiler/info.h"
#include "shader_recompiler/ir/attribute.h" #include "shader_recompiler/ir/attribute.h"
#include "shader_recompiler/ir/basic_block.h" #include "shader_recompiler/ir/basic_block.h"
#include "shader_recompiler/ir/condition.h" #include "shader_recompiler/ir/condition.h"
@ -43,6 +44,7 @@ public:
void Epilogue(); void Epilogue();
void Discard(); void Discard();
void Discard(const U1& cond); void Discard(const U1& cond);
void DebugPrint(const char* fmt, boost::container::small_vector<Value, 5> args);
void Barrier(); void Barrier();
void WorkgroupMemoryBarrier(); void WorkgroupMemoryBarrier();

View File

@ -89,6 +89,7 @@ bool Inst::MayHaveSideEffects() const noexcept {
case Opcode::ImageAtomicOr32: case Opcode::ImageAtomicOr32:
case Opcode::ImageAtomicXor32: case Opcode::ImageAtomicXor32:
case Opcode::ImageAtomicExchange32: case Opcode::ImageAtomicExchange32:
case Opcode::DebugPrint:
case Opcode::EmitVertex: case Opcode::EmitVertex:
case Opcode::EmitPrimitive: case Opcode::EmitPrimitive:
return true; return true;

View File

@ -51,6 +51,7 @@ constexpr Type F32x4{Type::F32x4};
constexpr Type F64x2{Type::F64x2}; constexpr Type F64x2{Type::F64x2};
constexpr Type F64x3{Type::F64x3}; constexpr Type F64x3{Type::F64x3};
constexpr Type F64x4{Type::F64x4}; constexpr Type F64x4{Type::F64x4};
constexpr Type StringLiteral{Type::StringLiteral};
constexpr OpcodeMeta META_TABLE[]{ constexpr OpcodeMeta META_TABLE[]{
#define OPCODE(name_token, type_token, ...) \ #define OPCODE(name_token, type_token, ...) \
@ -81,7 +82,7 @@ constexpr u8 NUM_ARGS[]{
} }
/// Get the number of arguments an opcode accepts /// Get the number of arguments an opcode accepts
[[nodiscard]] inline size_t NumArgsOf(Opcode op) noexcept { [[nodiscard]] constexpr inline size_t NumArgsOf(Opcode op) noexcept {
return static_cast<size_t>(Detail::NUM_ARGS[static_cast<size_t>(op)]); return static_cast<size_t>(Detail::NUM_ARGS[static_cast<size_t>(op)]);
} }

View File

@ -14,6 +14,7 @@ OPCODE(Prologue, Void,
OPCODE(Epilogue, Void, ) OPCODE(Epilogue, Void, )
OPCODE(Discard, Void, ) OPCODE(Discard, Void, )
OPCODE(DiscardCond, Void, U1, ) OPCODE(DiscardCond, Void, U1, )
OPCODE(DebugPrint, Void, StringLiteral, Opaque, Opaque, Opaque, Opaque, )
// Constant memory operations // Constant memory operations
OPCODE(ReadConst, U32, U32x2, U32, ) OPCODE(ReadConst, U32, U32x2, U32, )

View File

@ -11,8 +11,7 @@ std::string NameOf(Type type) {
static constexpr std::array names{ static constexpr std::array names{
"Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32", "Opaque", "Label", "Reg", "Pred", "Attribute", "U1", "U8", "U16", "U32",
"U64", "F16", "F32", "F64", "U32x2", "U32x3", "U32x4", "F16x2", "F16x3", "U64", "F16", "F32", "F64", "U32x2", "U32x3", "U32x4", "F16x2", "F16x3",
"F16x4", "F32x2", "F32x3", "F32x4", "F64x2", "F64x3", "F64x4", "F16x4", "F32x2", "F32x3", "F32x4", "F64x2", "F64x3", "F64x4", "StringLiteral"};
};
const size_t bits{static_cast<size_t>(type)}; const size_t bits{static_cast<size_t>(type)};
if (bits == 0) { if (bits == 0) {
return "Void"; return "Void";

View File

@ -36,6 +36,7 @@ enum class Type {
F64x2 = 1 << 22, F64x2 = 1 << 22,
F64x3 = 1 << 23, F64x3 = 1 << 23,
F64x4 = 1 << 24, F64x4 = 1 << 24,
StringLiteral = 1 << 25,
}; };
DECLARE_ENUM_FLAG_OPERATORS(Type) DECLARE_ENUM_FLAG_OPERATORS(Type)

View File

@ -1,6 +1,7 @@
// 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 <string>
#include "shader_recompiler/ir/value.h" #include "shader_recompiler/ir/value.h"
namespace Shader::IR { namespace Shader::IR {
@ -27,6 +28,8 @@ Value::Value(u64 value) noexcept : type{Type::U64}, imm_u64{value} {}
Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {} Value::Value(f64 value) noexcept : type{Type::F64}, imm_f64{value} {}
Value::Value(const char* value) noexcept : type{Type::StringLiteral}, string_literal{value} {}
IR::Type Value::Type() const noexcept { IR::Type Value::Type() const noexcept {
if (IsPhi()) { if (IsPhi()) {
// The type of a phi node is stored in its flags // The type of a phi node is stored in its flags
@ -69,6 +72,8 @@ bool Value::operator==(const Value& other) const {
case Type::U64: case Type::U64:
case Type::F64: case Type::F64:
return imm_u64 == other.imm_u64; return imm_u64 == other.imm_u64;
case Type::StringLiteral:
return std::string_view(string_literal) == other.string_literal;
case Type::U32x2: case Type::U32x2:
case Type::U32x3: case Type::U32x3:
case Type::U32x4: case Type::U32x4:

View File

@ -39,6 +39,7 @@ public:
explicit Value(f32 value) noexcept; explicit Value(f32 value) noexcept;
explicit Value(u64 value) noexcept; explicit Value(u64 value) noexcept;
explicit Value(f64 value) noexcept; explicit Value(f64 value) noexcept;
explicit Value(const char* value) noexcept;
[[nodiscard]] bool IsIdentity() const noexcept; [[nodiscard]] bool IsIdentity() const noexcept;
[[nodiscard]] bool IsPhi() const noexcept; [[nodiscard]] bool IsPhi() const noexcept;
@ -60,6 +61,7 @@ public:
[[nodiscard]] f32 F32() const; [[nodiscard]] f32 F32() const;
[[nodiscard]] u64 U64() const; [[nodiscard]] u64 U64() const;
[[nodiscard]] f64 F64() const; [[nodiscard]] f64 F64() const;
[[nodiscard]] const char* StringLiteral() const;
[[nodiscard]] bool operator==(const Value& other) const; [[nodiscard]] bool operator==(const Value& other) const;
[[nodiscard]] bool operator!=(const Value& other) const; [[nodiscard]] bool operator!=(const Value& other) const;
@ -78,6 +80,7 @@ private:
f32 imm_f32; f32 imm_f32;
u64 imm_u64; u64 imm_u64;
f64 imm_f64; f64 imm_f64;
const char* string_literal;
}; };
}; };
static_assert(static_cast<u32>(IR::Type::Void) == 0, "memset relies on IR::Type being zero"); static_assert(static_cast<u32>(IR::Type::Void) == 0, "memset relies on IR::Type being zero");
@ -348,6 +351,14 @@ inline f64 Value::F64() const {
return imm_f64; return imm_f64;
} }
inline const char* Value::StringLiteral() const {
if (IsIdentity()) {
return inst->Arg(0).StringLiteral();
}
DEBUG_ASSERT(type == Type::StringLiteral);
return string_literal;
}
[[nodiscard]] inline bool IsPhi(const Inst& inst) { [[nodiscard]] inline bool IsPhi(const Inst& inst) {
return inst.GetOpcode() == Opcode::Phi; return inst.GetOpcode() == Opcode::Phi;
} }

View File

@ -142,6 +142,9 @@ struct PageManager::Impl {
} }
void Protect(VAddr address, size_t size, bool allow_write) { void Protect(VAddr address, size_t size, bool allow_write) {
ASSERT_MSG(owned_ranges.find(address) != owned_ranges.end(),
"Attempted to track non-GPU memory at address {:#x}, size {:#x}.", address,
size);
#ifdef _WIN32 #ifdef _WIN32
DWORD prot = allow_write ? PAGE_READWRITE : PAGE_READONLY; DWORD prot = allow_write ? PAGE_READWRITE : PAGE_READONLY;
DWORD old_prot{}; DWORD old_prot{};