mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-22 18:15:14 +00:00
Merge branch 'main' into presets-fix
This commit is contained in:
commit
ed1b7d7620
2
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
2
.github/ISSUE_TEMPLATE/game-bug-report.yaml
vendored
@ -35,7 +35,7 @@ body:
|
||||
required: true
|
||||
- label: I have disabled all patches and cheats and the issue is still present.
|
||||
required: true
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadps4-game-compatibility?tab=readme-ov-file#informations) installed.
|
||||
- label: I have all the required [system modules](https://github.com/shadps4-emu/shadPS4/wiki/I.-Quick-start-%5BUsers%5D#4-adding-modules) installed.
|
||||
required: true
|
||||
- type: textarea
|
||||
id: desc
|
||||
|
@ -683,6 +683,7 @@ set(COMMON src/common/logging/backend.cpp
|
||||
src/common/path_util.h
|
||||
src/common/object_pool.h
|
||||
src/common/polyfill_thread.h
|
||||
src/common/range_lock.h
|
||||
src/common/rdtsc.cpp
|
||||
src/common/rdtsc.h
|
||||
src/common/recursive_lock.cpp
|
||||
@ -1067,6 +1068,8 @@ set(QT_GUI src/qt_gui/about_dialog.cpp
|
||||
src/qt_gui/gui_settings.h
|
||||
src/qt_gui/settings.cpp
|
||||
src/qt_gui/settings.h
|
||||
src/qt_gui/sdl_event_wrapper.cpp
|
||||
src/qt_gui/sdl_event_wrapper.h
|
||||
${EMULATOR}
|
||||
${RESOURCE_FILES}
|
||||
${TRANSLATIONS}
|
||||
|
@ -10,7 +10,7 @@
|
||||
{
|
||||
"name": "x64-Clang-Debug",
|
||||
"displayName": "Clang x64 Debug",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"inherits": [ "x64-Windows-Base" ],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug"
|
||||
}
|
||||
@ -18,16 +18,12 @@
|
||||
{
|
||||
"name": "x64-Clang-Debug-Qt",
|
||||
"displayName": "Clang x64 Debug with Qt",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Debug",
|
||||
"ENABLE_QT_GUI": "ON"
|
||||
}
|
||||
"inherits": [ "x64-Clang-Debug", "Qt-GUI" ]
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-Release",
|
||||
"displayName": "Clang x64 Release",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"inherits": [ "x64-Windows-Base" ],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release"
|
||||
}
|
||||
@ -35,16 +31,12 @@
|
||||
{
|
||||
"name": "x64-Clang-Release-Qt",
|
||||
"displayName": "Clang x64 Release with Qt",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "Release",
|
||||
"ENABLE_QT_GUI": "ON"
|
||||
}
|
||||
"inherits": [ "x64-Clang-Release", "Qt-GUI" ]
|
||||
},
|
||||
{
|
||||
"name": "x64-Clang-RelWithDebInfo",
|
||||
"displayName": "Clang x64 RelWithDebInfo",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"inherits": [ "x64-Windows-Base" ],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
|
||||
}
|
||||
@ -52,11 +44,7 @@
|
||||
{
|
||||
"name": "x64-Clang-RelWithDebInfo-Qt",
|
||||
"displayName": "Clang x64 RelWithDebInfo with Qt",
|
||||
"inherits": ["x64-Clang-Base"],
|
||||
"cacheVariables": {
|
||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||
"ENABLE_QT_GUI": "ON"
|
||||
}
|
||||
"inherits": [ "x64-Clang-RelWithDebInfo", "Qt-GUI" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
@ -18,6 +18,9 @@ public:
|
||||
void unlock() {
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
[[nodiscard]] bool try_lock() {
|
||||
return pthread_mutex_trylock(&mutex) == 0;
|
||||
}
|
||||
|
||||
private:
|
||||
pthread_mutex_t mutex = PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP;
|
||||
|
@ -361,13 +361,6 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline constexpr BitArray& operator~() {
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
data[i] = ~data[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline constexpr BitArray operator|(const BitArray& other) const {
|
||||
BitArray result = *this;
|
||||
result |= other;
|
||||
@ -388,7 +381,9 @@ public:
|
||||
|
||||
inline constexpr BitArray operator~() const {
|
||||
BitArray result = *this;
|
||||
result = ~result;
|
||||
for (size_t i = 0; i < WORD_COUNT; ++i) {
|
||||
result.data[i] = ~result.data[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
101
src/common/range_lock.h
Normal file
101
src/common/range_lock.h
Normal file
@ -0,0 +1,101 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2025 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <iterator>
|
||||
#include <mutex>
|
||||
|
||||
namespace Common {
|
||||
|
||||
// From boost thread locking
|
||||
|
||||
template <typename Iterator>
|
||||
struct RangeLockGuard {
|
||||
Iterator begin;
|
||||
Iterator end;
|
||||
|
||||
RangeLockGuard(Iterator begin_, Iterator end_) : begin(begin_), end(end_) {
|
||||
LockRange(begin, end);
|
||||
}
|
||||
|
||||
void release() {
|
||||
begin = end;
|
||||
}
|
||||
|
||||
~RangeLockGuard() {
|
||||
for (; begin != end; ++begin) {
|
||||
begin->unlock();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator>
|
||||
Iterator TryLockRange(Iterator begin, Iterator end) {
|
||||
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||
|
||||
if (begin == end) {
|
||||
return end;
|
||||
}
|
||||
|
||||
std::unique_lock<LockType> guard(*begin, std::try_to_lock);
|
||||
if (!guard.owns_lock()) {
|
||||
return begin;
|
||||
}
|
||||
|
||||
Iterator failed = TryLockRange(++begin, end);
|
||||
if (failed == end) {
|
||||
guard.release();
|
||||
}
|
||||
|
||||
return failed;
|
||||
}
|
||||
|
||||
template <typename Iterator>
|
||||
void LockRange(Iterator begin, Iterator end) {
|
||||
using LockType = typename std::iterator_traits<Iterator>::value_type;
|
||||
|
||||
if (begin == end) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool start_with_begin = true;
|
||||
Iterator second = begin;
|
||||
++second;
|
||||
Iterator next = second;
|
||||
|
||||
while (true) {
|
||||
std::unique_lock<LockType> begin_lock(*begin, std::defer_lock);
|
||||
if (start_with_begin) {
|
||||
begin_lock.lock();
|
||||
|
||||
const Iterator failed_lock = TryLockRange(next, end);
|
||||
if (failed_lock == end) {
|
||||
begin_lock.release();
|
||||
return;
|
||||
}
|
||||
|
||||
start_with_begin = false;
|
||||
next = failed_lock;
|
||||
} else {
|
||||
RangeLockGuard<Iterator> guard(next, end);
|
||||
|
||||
if (begin_lock.try_lock()) {
|
||||
const Iterator failed_lock = TryLockRange(second, next);
|
||||
if (failed_lock == next) {
|
||||
begin_lock.release();
|
||||
guard.release();
|
||||
return;
|
||||
}
|
||||
|
||||
start_with_begin = false;
|
||||
next = failed_lock;
|
||||
} else {
|
||||
start_with_begin = true;
|
||||
next = second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Common
|
@ -171,19 +171,40 @@ s32 PS4_SYSV_ABI sceVideodec2GetPictureInfo(const OrbisVideodec2OutputInfo* outp
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
if (outputInfo->pictureCount == 0 || gPictureInfos.empty()) {
|
||||
if (outputInfo->pictureCount == 0) {
|
||||
LOG_ERROR(Lib_Vdec2, "No picture info available");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
|
||||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2AvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2AvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if ((picInfo->thisSize | 16) != sizeof(OrbisVideodec2AvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
// If the game uses the older Videodec2 structs, we need to accomodate that.
|
||||
if (outputInfo->thisSize != sizeof(OrbisVideodec2OutputInfo)) {
|
||||
if (gLegacyPictureInfos.empty()) {
|
||||
LOG_ERROR(Lib_Vdec2, "No picture info available");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2LegacyAvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2LegacyAvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if (picInfo->thisSize != sizeof(OrbisVideodec2LegacyAvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
*picInfo = gLegacyPictureInfos.back();
|
||||
}
|
||||
} else {
|
||||
if (gPictureInfos.empty()) {
|
||||
LOG_ERROR(Lib_Vdec2, "No picture info available");
|
||||
return ORBIS_OK;
|
||||
}
|
||||
if (p1stPictureInfoOut) {
|
||||
OrbisVideodec2AvcPictureInfo* picInfo =
|
||||
static_cast<OrbisVideodec2AvcPictureInfo*>(p1stPictureInfoOut);
|
||||
if (picInfo->thisSize != sizeof(OrbisVideodec2AvcPictureInfo)) {
|
||||
LOG_ERROR(Lib_Vdec2, "Invalid struct size");
|
||||
return ORBIS_VIDEODEC2_ERROR_STRUCT_SIZE;
|
||||
}
|
||||
*picInfo = gPictureInfos.back();
|
||||
}
|
||||
*picInfo = gPictureInfos.back();
|
||||
}
|
||||
|
||||
if (outputInfo->pictureCount > 1) {
|
||||
|
@ -74,4 +74,57 @@ struct OrbisVideodec2AvcPictureInfo {
|
||||
};
|
||||
static_assert(sizeof(OrbisVideodec2AvcPictureInfo) == 0x78);
|
||||
|
||||
// An older version of the OrbisVideodec2AvcPictureInfo struct
|
||||
// Keeping this is needed for compatiblity with older games.
|
||||
struct OrbisVideodec2LegacyAvcPictureInfo {
|
||||
u64 thisSize;
|
||||
|
||||
bool isValid;
|
||||
|
||||
u64 ptsData;
|
||||
u64 dtsData;
|
||||
u64 attachedData;
|
||||
|
||||
u8 idrPictureflag;
|
||||
|
||||
u8 profile_idc;
|
||||
u8 level_idc;
|
||||
u32 pic_width_in_mbs_minus1;
|
||||
u32 pic_height_in_map_units_minus1;
|
||||
u8 frame_mbs_only_flag;
|
||||
|
||||
u8 frame_cropping_flag;
|
||||
u32 frameCropLeftOffset;
|
||||
u32 frameCropRightOffset;
|
||||
u32 frameCropTopOffset;
|
||||
u32 frameCropBottomOffset;
|
||||
|
||||
u8 aspect_ratio_info_present_flag;
|
||||
u8 aspect_ratio_idc;
|
||||
u16 sar_width;
|
||||
u16 sar_height;
|
||||
|
||||
u8 video_signal_type_present_flag;
|
||||
u8 video_format;
|
||||
u8 video_full_range_flag;
|
||||
u8 colour_description_present_flag;
|
||||
u8 colour_primaries;
|
||||
u8 transfer_characteristics;
|
||||
u8 matrix_coefficients;
|
||||
|
||||
u8 timing_info_present_flag;
|
||||
u32 num_units_in_tick;
|
||||
u32 time_scale;
|
||||
u8 fixed_frame_rate_flag;
|
||||
|
||||
u8 bitstream_restriction_flag;
|
||||
u8 max_dec_frame_buffering;
|
||||
|
||||
u8 pic_struct_present_flag;
|
||||
u8 pic_struct;
|
||||
u8 field_pic_flag;
|
||||
u8 bottom_field_flag;
|
||||
};
|
||||
static_assert(sizeof(OrbisVideodec2LegacyAvcPictureInfo) == 0x68);
|
||||
|
||||
} // namespace Libraries::Vdec2
|
@ -12,6 +12,7 @@
|
||||
namespace Libraries::Vdec2 {
|
||||
|
||||
std::vector<OrbisVideodec2AvcPictureInfo> gPictureInfos;
|
||||
std::vector<OrbisVideodec2LegacyAvcPictureInfo> gLegacyPictureInfos;
|
||||
|
||||
static inline void CopyNV12Data(u8* dst, const AVFrame& src) {
|
||||
std::memcpy(dst, src.data[0], src.width * src.height);
|
||||
@ -117,27 +118,46 @@ s32 VdecDecoder::Decode(const OrbisVideodec2InputData& inputData,
|
||||
outputInfo.isErrorFrame = false;
|
||||
outputInfo.pictureCount = 1; // TODO: 2 pictures for interlaced video
|
||||
|
||||
// Only set framePitchInBytes if the game uses the newer struct version.
|
||||
// For proper compatibility with older games, check the inputted OutputInfo struct size.
|
||||
if (outputInfo.thisSize == sizeof(OrbisVideodec2OutputInfo)) {
|
||||
// framePitchInBytes only exists in the newer struct.
|
||||
outputInfo.framePitchInBytes = frame->linesize[0];
|
||||
}
|
||||
if (outputInfo.isValid) {
|
||||
OrbisVideodec2AvcPictureInfo pictureInfo = {};
|
||||
|
||||
if (outputInfo.isValid) {
|
||||
OrbisVideodec2AvcPictureInfo pictureInfo = {};
|
||||
pictureInfo.thisSize = sizeof(OrbisVideodec2AvcPictureInfo);
|
||||
pictureInfo.isValid = true;
|
||||
|
||||
pictureInfo.thisSize = sizeof(OrbisVideodec2AvcPictureInfo);
|
||||
pictureInfo.isValid = true;
|
||||
pictureInfo.ptsData = inputData.ptsData;
|
||||
pictureInfo.dtsData = inputData.dtsData;
|
||||
pictureInfo.attachedData = inputData.attachedData;
|
||||
|
||||
pictureInfo.ptsData = inputData.ptsData;
|
||||
pictureInfo.dtsData = inputData.dtsData;
|
||||
pictureInfo.attachedData = inputData.attachedData;
|
||||
pictureInfo.frameCropLeftOffset = frame->crop_left;
|
||||
pictureInfo.frameCropRightOffset = frame->crop_right;
|
||||
pictureInfo.frameCropTopOffset = frame->crop_top;
|
||||
pictureInfo.frameCropBottomOffset = frame->crop_bottom;
|
||||
|
||||
pictureInfo.frameCropLeftOffset = frame->crop_left;
|
||||
pictureInfo.frameCropRightOffset = frame->crop_right;
|
||||
pictureInfo.frameCropTopOffset = frame->crop_top;
|
||||
pictureInfo.frameCropBottomOffset = frame->crop_bottom;
|
||||
gPictureInfos.push_back(pictureInfo);
|
||||
}
|
||||
} else {
|
||||
if (outputInfo.isValid) {
|
||||
// If the game uses the older struct versions, we need to use it too.
|
||||
OrbisVideodec2LegacyAvcPictureInfo pictureInfo = {};
|
||||
|
||||
gPictureInfos.push_back(pictureInfo);
|
||||
pictureInfo.thisSize = sizeof(OrbisVideodec2LegacyAvcPictureInfo);
|
||||
pictureInfo.isValid = true;
|
||||
|
||||
pictureInfo.ptsData = inputData.ptsData;
|
||||
pictureInfo.dtsData = inputData.dtsData;
|
||||
pictureInfo.attachedData = inputData.attachedData;
|
||||
|
||||
pictureInfo.frameCropLeftOffset = frame->crop_left;
|
||||
pictureInfo.frameCropRightOffset = frame->crop_right;
|
||||
pictureInfo.frameCropTopOffset = frame->crop_top;
|
||||
pictureInfo.frameCropBottomOffset = frame->crop_bottom;
|
||||
|
||||
gLegacyPictureInfos.push_back(pictureInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,7 @@ extern "C" {
|
||||
namespace Libraries::Vdec2 {
|
||||
|
||||
extern std::vector<OrbisVideodec2AvcPictureInfo> gPictureInfos;
|
||||
extern std::vector<OrbisVideodec2LegacyAvcPictureInfo> gLegacyPictureInfos;
|
||||
|
||||
class VdecDecoder {
|
||||
public:
|
||||
|
@ -177,38 +177,38 @@ const std::map<std::string, u32> string_to_keyboard_key_map = {
|
||||
{"9", SDLK_9},
|
||||
|
||||
// symbols
|
||||
{"`", SDLK_GRAVE},
|
||||
{"~", SDLK_TILDE},
|
||||
{"!", SDLK_EXCLAIM},
|
||||
{"@", SDLK_AT},
|
||||
{"#", SDLK_HASH},
|
||||
{"$", SDLK_DOLLAR},
|
||||
{"%", SDLK_PERCENT},
|
||||
{"^", SDLK_CARET},
|
||||
{"&", SDLK_AMPERSAND},
|
||||
{"*", SDLK_ASTERISK},
|
||||
{"(", SDLK_LEFTPAREN},
|
||||
{")", SDLK_RIGHTPAREN},
|
||||
{"-", SDLK_MINUS},
|
||||
{"_", SDLK_UNDERSCORE},
|
||||
{"=", SDLK_EQUALS},
|
||||
{"+", SDLK_PLUS},
|
||||
{"[", SDLK_LEFTBRACKET},
|
||||
{"]", SDLK_RIGHTBRACKET},
|
||||
{"{", SDLK_LEFTBRACE},
|
||||
{"}", SDLK_RIGHTBRACE},
|
||||
{"\\", SDLK_BACKSLASH},
|
||||
{"|", SDLK_PIPE},
|
||||
{";", SDLK_SEMICOLON},
|
||||
{":", SDLK_COLON},
|
||||
{"'", SDLK_APOSTROPHE},
|
||||
{"\"", SDLK_DBLAPOSTROPHE},
|
||||
{",", SDLK_COMMA},
|
||||
{"<", SDLK_LESS},
|
||||
{".", SDLK_PERIOD},
|
||||
{">", SDLK_GREATER},
|
||||
{"/", SDLK_SLASH},
|
||||
{"?", SDLK_QUESTION},
|
||||
{"grave", SDLK_GRAVE},
|
||||
{"tilde", SDLK_TILDE},
|
||||
{"exclamation", SDLK_EXCLAIM},
|
||||
{"at", SDLK_AT},
|
||||
{"hash", SDLK_HASH},
|
||||
{"dollar", SDLK_DOLLAR},
|
||||
{"percent", SDLK_PERCENT},
|
||||
{"caret", SDLK_CARET},
|
||||
{"ampersand", SDLK_AMPERSAND},
|
||||
{"asterisk", SDLK_ASTERISK},
|
||||
{"lparen", SDLK_LEFTPAREN},
|
||||
{"rparen", SDLK_RIGHTPAREN},
|
||||
{"minus", SDLK_MINUS},
|
||||
{"underscore", SDLK_UNDERSCORE},
|
||||
{"equals", SDLK_EQUALS},
|
||||
{"plus", SDLK_PLUS},
|
||||
{"lbracket", SDLK_LEFTBRACKET},
|
||||
{"rbracket", SDLK_RIGHTBRACKET},
|
||||
{"lbrace", SDLK_LEFTBRACE},
|
||||
{"rbrace", SDLK_RIGHTBRACE},
|
||||
{"backslash", SDLK_BACKSLASH},
|
||||
{"pipe", SDLK_PIPE},
|
||||
{"semicolon", SDLK_SEMICOLON},
|
||||
{"colon", SDLK_COLON},
|
||||
{"apostrophe", SDLK_APOSTROPHE},
|
||||
{"quote", SDLK_DBLAPOSTROPHE},
|
||||
{"comma", SDLK_COMMA},
|
||||
{"less", SDLK_LESS},
|
||||
{"period", SDLK_PERIOD},
|
||||
{"greater", SDLK_GREATER},
|
||||
{"slash", SDLK_SLASH},
|
||||
{"question", SDLK_QUESTION},
|
||||
|
||||
// special keys
|
||||
{"escape", SDLK_ESCAPE},
|
||||
@ -252,13 +252,13 @@ const std::map<std::string, u32> string_to_keyboard_key_map = {
|
||||
{"kp7", SDLK_KP_7},
|
||||
{"kp8", SDLK_KP_8},
|
||||
{"kp9", SDLK_KP_9},
|
||||
{"kp.", SDLK_KP_PERIOD},
|
||||
{"kp,", SDLK_KP_COMMA},
|
||||
{"kp/", SDLK_KP_DIVIDE},
|
||||
{"kp*", SDLK_KP_MULTIPLY},
|
||||
{"kp-", SDLK_KP_MINUS},
|
||||
{"kp+", SDLK_KP_PLUS},
|
||||
{"kp=", SDLK_KP_EQUALS},
|
||||
{"kpperiod", SDLK_KP_PERIOD},
|
||||
{"kpcomma", SDLK_KP_COMMA},
|
||||
{"kpslash", SDLK_KP_DIVIDE},
|
||||
{"kpasterisk", SDLK_KP_MULTIPLY},
|
||||
{"kpminus", SDLK_KP_MINUS},
|
||||
{"kpplus", SDLK_KP_PLUS},
|
||||
{"kpequals", SDLK_KP_EQUALS},
|
||||
{"kpenter", SDLK_KP_ENTER},
|
||||
|
||||
// mouse
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,10 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <QDialog>
|
||||
#include <SDL3/SDL.h>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
#include "game_info.h"
|
||||
#include "sdl_event_wrapper.h"
|
||||
|
||||
namespace Ui {
|
||||
class ControlSettings;
|
||||
@ -11,22 +14,56 @@ class ControlSettings;
|
||||
class ControlSettings : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit ControlSettings(std::shared_ptr<GameInfoClass> game_info_get,
|
||||
QWidget* parent = nullptr);
|
||||
explicit ControlSettings(std::shared_ptr<GameInfoClass> game_info_get, bool GameRunning,
|
||||
std::string GameRunningSerial, QWidget* parent = nullptr);
|
||||
~ControlSettings();
|
||||
|
||||
signals:
|
||||
void PushGamepadEvent();
|
||||
void AxisChanged();
|
||||
|
||||
private Q_SLOTS:
|
||||
void SaveControllerConfig(bool CloseOnSave);
|
||||
void SetDefault();
|
||||
void UpdateLightbarColor();
|
||||
void CheckMapping(QPushButton*& button);
|
||||
void StartTimer(QPushButton*& button, bool isButton);
|
||||
void ConnectAxisInputs(QPushButton*& button);
|
||||
|
||||
private:
|
||||
std::unique_ptr<Ui::ControlSettings> ui;
|
||||
std::shared_ptr<GameInfoClass> m_game_info;
|
||||
|
||||
bool eventFilter(QObject* obj, QEvent* event) override;
|
||||
void AddBoxItems();
|
||||
void SetUIValuestoMappings();
|
||||
void GetGameTitle();
|
||||
void CheckGamePad();
|
||||
void processSDLEvents(int Type, int Input, int Value);
|
||||
void pollSDLEvents();
|
||||
void SetMapping(QString input);
|
||||
void DisableMappingButtons();
|
||||
void EnableMappingButtons();
|
||||
void Cleanup();
|
||||
|
||||
QList<QPushButton*> ButtonsList;
|
||||
QList<QPushButton*> AxisList;
|
||||
QSet<QString> pressedButtons;
|
||||
|
||||
std::string RunningGameSerial;
|
||||
bool GameRunning;
|
||||
bool L2Pressed = false;
|
||||
bool R2Pressed = false;
|
||||
bool EnableButtonMapping = false;
|
||||
bool EnableAxisMapping = false;
|
||||
bool MappingCompleted = false;
|
||||
QString mapping;
|
||||
int MappingTimer;
|
||||
QTimer* timer;
|
||||
QPushButton* MappingButton;
|
||||
SDL_Gamepad* gamepad = nullptr;
|
||||
SdlEventWrapper::Wrapper* RemapWrapper;
|
||||
QFuture<void> Polling;
|
||||
|
||||
const std::vector<std::string> ControllerInputs = {
|
||||
"cross", "circle", "square", "triangle", "l1",
|
||||
@ -39,29 +76,8 @@ private:
|
||||
"pad_left", "pad_right", "axis_left_x", "axis_left_y", "axis_right_x",
|
||||
"axis_right_y", "back"};
|
||||
|
||||
const QStringList ButtonOutputs = {"cross",
|
||||
"circle",
|
||||
"square",
|
||||
"triangle",
|
||||
"l1",
|
||||
"r1",
|
||||
"l2",
|
||||
"r2",
|
||||
"l3",
|
||||
|
||||
"r3",
|
||||
"options",
|
||||
"pad_up",
|
||||
|
||||
"pad_down",
|
||||
|
||||
"pad_left",
|
||||
"pad_right",
|
||||
"touchpad_left",
|
||||
"touchpad_center",
|
||||
"touchpad_right",
|
||||
"unmapped"};
|
||||
|
||||
const QStringList StickOutputs = {"axis_left_x", "axis_left_y", "axis_right_x", "axis_right_y",
|
||||
"unmapped"};
|
||||
protected:
|
||||
void closeEvent(QCloseEvent* event) override {
|
||||
Cleanup();
|
||||
}
|
||||
};
|
||||
|
@ -11,8 +11,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1043</width>
|
||||
<height>792</height>
|
||||
<width>1114</width>
|
||||
<height>794</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -33,8 +33,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1019</width>
|
||||
<height>732</height>
|
||||
<width>1094</width>
|
||||
<height>744</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
@ -42,8 +42,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1021</width>
|
||||
<height>731</height>
|
||||
<width>1091</width>
|
||||
<height>741</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="RemapLayout">
|
||||
@ -110,7 +110,7 @@
|
||||
<widget class="QGroupBox" name="gb_dpad_up">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -125,12 +125,9 @@
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QComboBox" name="DpadUpBox">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sizeAdjustPolicy">
|
||||
<enum>QComboBox::SizeAdjustPolicy::AdjustToContents</enum>
|
||||
<widget class="QPushButton" name="DpadUpButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -161,7 +158,11 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="DpadLeftBox"/>
|
||||
<widget class="QPushButton" name="DpadLeftButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -185,9 +186,9 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="DpadRightBox">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
<widget class="QPushButton" name="DpadRightButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -213,6 +214,12 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_dpad_down">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>152</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
@ -224,21 +231,9 @@
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QComboBox" name="DpadDownBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
<widget class="QPushButton" name="DpadDownButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -378,7 +373,7 @@
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -387,9 +382,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
<item>
|
||||
<widget class="QComboBox" name="LStickUpBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="LStickUpButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -420,9 +415,9 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="LStickLeftBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="LStickLeftButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -454,9 +449,9 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="LStickRightBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="LStickRightButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -484,7 +479,7 @@
|
||||
<widget class="QGroupBox" name="gb_left_stick_down">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -499,15 +494,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_8">
|
||||
<item>
|
||||
<widget class="QComboBox" name="LStickDownBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="frame">
|
||||
<bool>false</bool>
|
||||
<widget class="QPushButton" name="LStickDownButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -617,149 +606,190 @@
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layout_l1_l2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_l1">
|
||||
<property name="title">
|
||||
<string>L1 / LB</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_l1_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="LBBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_l2">
|
||||
<property name="title">
|
||||
<string>L2 / LT</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_l2_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="LTBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layout_system_buttons">
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Preferred</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_4">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Back</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<item>
|
||||
<widget class="QComboBox" name="BackBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_13">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_l1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>L1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_l1_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="L1Button">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>133</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_r1">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>R1</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_r1_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="R1Button">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_14">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_l2">
|
||||
<property name="title">
|
||||
<string>L2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_l2_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="L2Button">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_start">
|
||||
<property name="title">
|
||||
<string>Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_start_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="OptionsButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_r2">
|
||||
<property name="title">
|
||||
<string>R2</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_r2_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="R2Button">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="layout_r1_r2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_r1">
|
||||
<property name="title">
|
||||
<string>R1 / RB</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_r1_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="RBBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_r2">
|
||||
<property name="title">
|
||||
<string>R2 / RT</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_r2_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="RTBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
@ -806,7 +836,7 @@
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="layout_middle_bottom">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_9">
|
||||
<property name="spacing">
|
||||
<number>10</number>
|
||||
</property>
|
||||
@ -814,76 +844,144 @@
|
||||
<enum>QLayout::SizeConstraint::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_l3">
|
||||
<property name="title">
|
||||
<string>L3</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_l3_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="LClickBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_l3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>L3</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_l3_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="L3Button">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Orientation::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Policy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>133</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_r3">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>R3</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_r3_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="R3Button">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_start">
|
||||
<property name="title">
|
||||
<string>Options / Start</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_start_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="StartBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_r3">
|
||||
<property name="title">
|
||||
<string>R3</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_r3_layout">
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="RClickBox"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_touchleft">
|
||||
<property name="title">
|
||||
<string>Touchpad Left</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QPushButton" name="TouchpadLeftButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_touchcenter">
|
||||
<property name="title">
|
||||
<string>Touchpad Center</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
<item>
|
||||
<widget class="QPushButton" name="TouchpadCenterButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_touchright">
|
||||
<property name="title">
|
||||
<string>Touchpad Right</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<widget class="QPushButton" name="TouchpadRightButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
@ -1104,7 +1202,7 @@
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1115,19 +1213,13 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Triangle / Y</string>
|
||||
<string>Triangle</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QComboBox" name="YBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
<widget class="QPushButton" name="TriangleButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1142,7 +1234,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_square">
|
||||
<property name="title">
|
||||
<string>Square / X</string>
|
||||
<string>Square</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_square_layout">
|
||||
<property name="leftMargin">
|
||||
@ -1158,7 +1250,11 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="XBox"/>
|
||||
<widget class="QPushButton" name="SquareButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -1166,7 +1262,7 @@
|
||||
<item>
|
||||
<widget class="QGroupBox" name="gb_circle">
|
||||
<property name="title">
|
||||
<string>Circle / B</string>
|
||||
<string>Circle</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="gb_circle_layout">
|
||||
<property name="leftMargin">
|
||||
@ -1182,7 +1278,11 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="BBox"/>
|
||||
<widget class="QPushButton" name="CircleButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -1208,7 +1308,7 @@
|
||||
<widget class="QGroupBox" name="gb_cross">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1219,11 +1319,15 @@
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Cross / A</string>
|
||||
<string>Cross</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_5">
|
||||
<item>
|
||||
<widget class="QComboBox" name="ABox"/>
|
||||
<widget class="QPushButton" name="CrossButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -1361,7 +1465,7 @@
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>1231321</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1370,9 +1474,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_7">
|
||||
<item>
|
||||
<widget class="QComboBox" name="RStickUpBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="RStickUpButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1403,9 +1507,9 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="RStickLeftBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="RStickLeftButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@ -1431,7 +1535,11 @@
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QComboBox" name="RStickRightBox"/>
|
||||
<widget class="QPushButton" name="RStickRightButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
@ -1457,7 +1565,7 @@
|
||||
<widget class="QGroupBox" name="gb_right_stick_down">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>124</width>
|
||||
<width>152</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
@ -1472,9 +1580,9 @@
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_6">
|
||||
<item>
|
||||
<widget class="QComboBox" name="RStickDownBox">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
<widget class="QPushButton" name="RStickDownButton">
|
||||
<property name="text">
|
||||
<string>unmapped</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
|
@ -7,16 +7,20 @@
|
||||
#include <QMouseEvent>
|
||||
#include <QPushButton>
|
||||
#include <QWheelEvent>
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
#include "common/path_util.h"
|
||||
#include "input/input_handler.h"
|
||||
#include "kbm_config_dialog.h"
|
||||
#include "kbm_gui.h"
|
||||
#include "kbm_help_dialog.h"
|
||||
#include "ui_kbm_gui.h"
|
||||
|
||||
HelpDialog* HelpWindow;
|
||||
KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent)
|
||||
: QDialog(parent), m_game_info(game_info_get), ui(new Ui::KBMSettings) {
|
||||
KBMSettings::KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, bool isGameRunning,
|
||||
std::string GameRunningSerial, QWidget* parent)
|
||||
: QDialog(parent), m_game_info(game_info_get), GameRunning(isGameRunning),
|
||||
RunningGameSerial(GameRunningSerial), ui(new Ui::KBMSettings) {
|
||||
|
||||
ui->setupUi(this);
|
||||
ui->PerGameCheckBox->setChecked(!Config::GetUseUnifiedInputConfig());
|
||||
@ -144,6 +148,8 @@ tr("Do you want to overwrite existing mappings with the mappings from the Common
|
||||
QString SOSString = tr("Speed Offset (def 0.125):") + " " + SOSValue;
|
||||
ui->SpeedOffsetLabel->setText(SOSString);
|
||||
});
|
||||
|
||||
connect(this, &KBMSettings::PushKBMEvent, this, [this]() { CheckMapping(MappingButton); });
|
||||
}
|
||||
|
||||
void KBMSettings::ButtonConnects() {
|
||||
@ -269,9 +275,17 @@ void KBMSettings::SaveKBMConfig(bool close_on_save) {
|
||||
output_string = line.substr(0, equal_pos - 1);
|
||||
input_string = line.substr(equal_pos + 2);
|
||||
|
||||
if (std::find(ControllerInputs.begin(), ControllerInputs.end(), input_string) !=
|
||||
ControllerInputs.end() ||
|
||||
output_string == "analog_deadzone" || output_string == "override_controller_color") {
|
||||
bool controllerInputdetected = false;
|
||||
for (std::string input : ControllerInputs) {
|
||||
// Needed to avoid detecting backspace while detecting back
|
||||
if (input_string.contains(input) && !input_string.contains("backspace")) {
|
||||
controllerInputdetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (controllerInputdetected || output_string == "analog_deadzone" ||
|
||||
output_string == "override_controller_color") {
|
||||
lines.push_back(line);
|
||||
}
|
||||
}
|
||||
@ -322,6 +336,11 @@ QString(tr("Cannot bind any unique input more than once. Duplicate inputs mapped
|
||||
Config::SetUseUnifiedInputConfig(!ui->PerGameCheckBox->isChecked());
|
||||
Config::save(Common::FS::GetUserPath(Common::FS::PathType::UserDir) / "config.toml");
|
||||
|
||||
if (GameRunning) {
|
||||
Config::GetUseUnifiedInputConfig() ? Input::ParseInputConfig("default")
|
||||
: Input::ParseInputConfig(RunningGameSerial);
|
||||
}
|
||||
|
||||
if (close_on_save)
|
||||
QWidget::close();
|
||||
}
|
||||
@ -388,8 +407,16 @@ void KBMSettings::SetUIValuestoMappings(std::string config_id) {
|
||||
std::string output_string = line.substr(0, equal_pos - 1);
|
||||
std::string input_string = line.substr(equal_pos + 2);
|
||||
|
||||
if (std::find(ControllerInputs.begin(), ControllerInputs.end(), input_string) ==
|
||||
ControllerInputs.end()) {
|
||||
bool controllerInputdetected = false;
|
||||
for (std::string input : ControllerInputs) {
|
||||
// Needed to avoid detecting backspace while detecting back
|
||||
if (input_string.contains(input) && !input_string.contains("backspace")) {
|
||||
controllerInputdetected = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!controllerInputdetected) {
|
||||
if (output_string == "cross") {
|
||||
ui->CrossButton->setText(QString::fromStdString(input_string));
|
||||
} else if (output_string == "circle") {
|
||||
@ -518,7 +545,6 @@ void KBMSettings::StartTimer(QPushButton*& button) {
|
||||
MappingTimer = 3;
|
||||
EnableMapping = true;
|
||||
MappingCompleted = false;
|
||||
modifier = "";
|
||||
mapping = button->text();
|
||||
|
||||
DisableMappingButtons();
|
||||
@ -711,92 +737,98 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
|
||||
break;
|
||||
|
||||
// symbols
|
||||
case Qt::Key_QuoteLeft:
|
||||
pressedKeys.insert("grave");
|
||||
break;
|
||||
case Qt::Key_AsciiTilde:
|
||||
pressedKeys.insert("tilde");
|
||||
break;
|
||||
case Qt::Key_Exclam:
|
||||
pressedKeys.insert("!");
|
||||
pressedKeys.insert("exclamation");
|
||||
break;
|
||||
case Qt::Key_At:
|
||||
pressedKeys.insert("@");
|
||||
pressedKeys.insert("at");
|
||||
break;
|
||||
case Qt::Key_NumberSign:
|
||||
pressedKeys.insert("#");
|
||||
pressedKeys.insert("hash");
|
||||
break;
|
||||
case Qt::Key_Dollar:
|
||||
pressedKeys.insert("$");
|
||||
pressedKeys.insert("dollar");
|
||||
break;
|
||||
case Qt::Key_Percent:
|
||||
pressedKeys.insert("%");
|
||||
pressedKeys.insert("percent");
|
||||
break;
|
||||
case Qt::Key_AsciiCircum:
|
||||
pressedKeys.insert("^");
|
||||
pressedKeys.insert("caret");
|
||||
break;
|
||||
case Qt::Key_Ampersand:
|
||||
pressedKeys.insert("&");
|
||||
pressedKeys.insert("ampersand");
|
||||
break;
|
||||
case Qt::Key_Asterisk:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp*", "*"));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpasterisk", "asterisk"));
|
||||
break;
|
||||
case Qt::Key_ParenLeft:
|
||||
pressedKeys.insert("(");
|
||||
pressedKeys.insert("lparen");
|
||||
break;
|
||||
case Qt::Key_ParenRight:
|
||||
pressedKeys.insert(")");
|
||||
pressedKeys.insert("rparen");
|
||||
break;
|
||||
case Qt::Key_Minus:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp-", "-"));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpminus", "minus"));
|
||||
break;
|
||||
case Qt::Key_Underscore:
|
||||
pressedKeys.insert("_");
|
||||
pressedKeys.insert("underscore");
|
||||
break;
|
||||
case Qt::Key_Equal:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp=", "="));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpequals", "equals"));
|
||||
break;
|
||||
case Qt::Key_Plus:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp+", "+"));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpplus", "plus"));
|
||||
break;
|
||||
case Qt::Key_BracketLeft:
|
||||
pressedKeys.insert("[");
|
||||
pressedKeys.insert("lbracket");
|
||||
break;
|
||||
case Qt::Key_BracketRight:
|
||||
pressedKeys.insert("]");
|
||||
pressedKeys.insert("rbracket");
|
||||
break;
|
||||
case Qt::Key_BraceLeft:
|
||||
pressedKeys.insert("{");
|
||||
pressedKeys.insert("lbrace");
|
||||
break;
|
||||
case Qt::Key_BraceRight:
|
||||
pressedKeys.insert("}");
|
||||
pressedKeys.insert("rbrace");
|
||||
break;
|
||||
case Qt::Key_Backslash:
|
||||
pressedKeys.insert("\\");
|
||||
pressedKeys.insert("backslash");
|
||||
break;
|
||||
case Qt::Key_Bar:
|
||||
pressedKeys.insert("|");
|
||||
pressedKeys.insert("pipe");
|
||||
break;
|
||||
case Qt::Key_Semicolon:
|
||||
pressedKeys.insert(";");
|
||||
pressedKeys.insert("semicolon");
|
||||
break;
|
||||
case Qt::Key_Colon:
|
||||
pressedKeys.insert(":");
|
||||
pressedKeys.insert("colon");
|
||||
break;
|
||||
case Qt::Key_Apostrophe:
|
||||
pressedKeys.insert("'");
|
||||
pressedKeys.insert("apostrophe");
|
||||
break;
|
||||
case Qt::Key_QuoteDbl:
|
||||
pressedKeys.insert("\"");
|
||||
pressedKeys.insert("quote");
|
||||
break;
|
||||
case Qt::Key_Comma:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp,", ","));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpcomma", "comma"));
|
||||
break;
|
||||
case Qt::Key_Less:
|
||||
pressedKeys.insert("<");
|
||||
pressedKeys.insert("less");
|
||||
break;
|
||||
case Qt::Key_Period:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp.", "."));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpperiod", "period"));
|
||||
break;
|
||||
case Qt::Key_Greater:
|
||||
pressedKeys.insert(">");
|
||||
pressedKeys.insert("greater");
|
||||
break;
|
||||
case Qt::Key_Slash:
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kp/", "/"));
|
||||
pressedKeys.insert(GetModifiedButton(Qt::KeypadModifier, "kpslash", "slash"));
|
||||
break;
|
||||
case Qt::Key_Question:
|
||||
pressedKeys.insert("question");
|
||||
@ -867,7 +899,6 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
|
||||
}
|
||||
break;
|
||||
case Qt::Key_Meta:
|
||||
activateWindow();
|
||||
#ifdef _WIN32
|
||||
pressedKeys.insert("lwin");
|
||||
#else
|
||||
@ -878,7 +909,6 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
|
||||
pressedKeys.insert("space");
|
||||
break;
|
||||
case Qt::Key_Up:
|
||||
activateWindow();
|
||||
pressedKeys.insert("up");
|
||||
break;
|
||||
case Qt::Key_Down:
|
||||
@ -903,80 +933,98 @@ bool KBMSettings::eventFilter(QObject* obj, QEvent* event) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if (pressedKeys.size() < 3) {
|
||||
switch (mouseEvent->button()) {
|
||||
case Qt::LeftButton:
|
||||
pressedKeys.insert("leftbutton");
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
pressedKeys.insert("rightbutton");
|
||||
break;
|
||||
case Qt::MiddleButton:
|
||||
pressedKeys.insert("middlebutton");
|
||||
break;
|
||||
case Qt::XButton1:
|
||||
pressedKeys.insert("sidebuttonback");
|
||||
break;
|
||||
case Qt::XButton2:
|
||||
pressedKeys.insert("sidebuttonforward");
|
||||
break;
|
||||
if (event->type() == QEvent::MouseButtonPress) {
|
||||
QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
if (pressedKeys.size() < 3) {
|
||||
switch (mouseEvent->button()) {
|
||||
case Qt::LeftButton:
|
||||
pressedKeys.insert("leftbutton");
|
||||
break;
|
||||
case Qt::RightButton:
|
||||
pressedKeys.insert("rightbutton");
|
||||
break;
|
||||
case Qt::MiddleButton:
|
||||
pressedKeys.insert("middlebutton");
|
||||
break;
|
||||
case Qt::XButton1:
|
||||
pressedKeys.insert("sidebuttonback");
|
||||
break;
|
||||
case Qt::XButton2:
|
||||
pressedKeys.insert("sidebuttonforward");
|
||||
break;
|
||||
|
||||
// default case
|
||||
default:
|
||||
break;
|
||||
// bottom text
|
||||
// default case
|
||||
default:
|
||||
break;
|
||||
// bottom text
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const QList<QPushButton*> AxisList = {
|
||||
ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton,
|
||||
ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton};
|
||||
const QList<QPushButton*> AxisList = {
|
||||
ui->LStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->LStickRightButton,
|
||||
ui->RStickUpButton, ui->LStickDownButton, ui->LStickLeftButton, ui->RStickRightButton};
|
||||
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
|
||||
if (pressedKeys.size() < 3) {
|
||||
if (wheelEvent->angleDelta().y() > 5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
|
||||
pressedKeys.insert("mousewheelup");
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
if (event->type() == QEvent::Wheel) {
|
||||
QWheelEvent* wheelEvent = static_cast<QWheelEvent*>(event);
|
||||
if (pressedKeys.size() < 3) {
|
||||
if (wheelEvent->angleDelta().y() > 5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) ==
|
||||
AxisList.end()) {
|
||||
pressedKeys.insert("mousewheelup");
|
||||
if (QApplication::keyboardModifiers() == Qt::NoModifier)
|
||||
emit PushKBMEvent();
|
||||
} else {
|
||||
QMessageBox::information(
|
||||
this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
}
|
||||
} else if (wheelEvent->angleDelta().y() < -5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) ==
|
||||
AxisList.end()) {
|
||||
pressedKeys.insert("mousewheeldown");
|
||||
if (QApplication::keyboardModifiers() == Qt::NoModifier)
|
||||
emit PushKBMEvent();
|
||||
} else {
|
||||
QMessageBox::information(
|
||||
this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
}
|
||||
}
|
||||
} else if (wheelEvent->angleDelta().y() < -5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
|
||||
pressedKeys.insert("mousewheeldown");
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
}
|
||||
}
|
||||
if (wheelEvent->angleDelta().x() > 5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
|
||||
// QT changes scrolling to horizontal for all widgets with the alt modifier
|
||||
pressedKeys.insert(
|
||||
GetModifiedButton(Qt::AltModifier, "mousewheelup", "mousewheelright"));
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
}
|
||||
} else if (wheelEvent->angleDelta().x() < -5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) == AxisList.end()) {
|
||||
pressedKeys.insert(
|
||||
GetModifiedButton(Qt::AltModifier, "mousewheeldown", "mousewheelleft"));
|
||||
} else {
|
||||
QMessageBox::information(this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
if (wheelEvent->angleDelta().x() > 5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) ==
|
||||
AxisList.end()) {
|
||||
// QT changes scrolling to horizontal for all widgets with the alt modifier
|
||||
pressedKeys.insert(
|
||||
GetModifiedButton(Qt::AltModifier, "mousewheelup", "mousewheelright"));
|
||||
if (QApplication::keyboardModifiers() == Qt::NoModifier)
|
||||
emit PushKBMEvent();
|
||||
} else {
|
||||
QMessageBox::information(
|
||||
this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
}
|
||||
} else if (wheelEvent->angleDelta().x() < -5) {
|
||||
if (std::find(AxisList.begin(), AxisList.end(), MappingButton) ==
|
||||
AxisList.end()) {
|
||||
pressedKeys.insert(
|
||||
GetModifiedButton(Qt::AltModifier, "mousewheeldown", "mousewheelleft"));
|
||||
if (QApplication::keyboardModifiers() == Qt::NoModifier)
|
||||
emit PushKBMEvent();
|
||||
} else {
|
||||
QMessageBox::information(
|
||||
this, tr("Cannot set mapping"),
|
||||
tr("Mousewheel cannot be mapped to stick outputs"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (event->type() == QEvent::KeyRelease || event->type() == QEvent::MouseButtonRelease)
|
||||
emit PushKBMEvent();
|
||||
}
|
||||
return QDialog::eventFilter(obj, event);
|
||||
}
|
||||
|
||||
|
@ -23,9 +23,13 @@ class KBMSettings;
|
||||
class KBMSettings : public QDialog {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, QWidget* parent = nullptr);
|
||||
explicit KBMSettings(std::shared_ptr<GameInfoClass> game_info_get, bool GameRunning,
|
||||
std::string GameRunningSerial, QWidget* parent = nullptr);
|
||||
~KBMSettings();
|
||||
|
||||
signals:
|
||||
void PushKBMEvent();
|
||||
|
||||
private Q_SLOTS:
|
||||
void SaveKBMConfig(bool CloseOnSave);
|
||||
void SetDefault();
|
||||
@ -44,13 +48,15 @@ private:
|
||||
void DisableMappingButtons();
|
||||
void EnableMappingButtons();
|
||||
void SetMapping(QString input);
|
||||
void Cleanup();
|
||||
|
||||
std::string RunningGameSerial;
|
||||
QSet<QString> pressedKeys;
|
||||
bool GameRunning;
|
||||
bool EnableMapping = false;
|
||||
bool MappingCompleted = false;
|
||||
bool HelpWindowOpen = false;
|
||||
QString mapping;
|
||||
QString modifier;
|
||||
int MappingTimer;
|
||||
QTimer* timer;
|
||||
QPushButton* MappingButton;
|
||||
|
@ -121,35 +121,6 @@ To view the config file's syntax, check out the Syntax tab, for keybind names, v
|
||||
This project began because I disliked the original, unchangeable keybinds. Rather than waiting for someone else to do it, I implemented this myself. From the default keybinds, you can clearly tell this was a project built for Bloodborne, but obviously, you can make adjustments however you like.)";
|
||||
}
|
||||
|
||||
QString HelpDialog::faq() {
|
||||
return R"(
|
||||
Q: What are the emulator-wide keybinds?
|
||||
A:
|
||||
-F12: Triggers Renderdoc capture
|
||||
-F11: Toggles fullscreen
|
||||
-F10: Toggles FPS counter
|
||||
-Ctrl+F10: Open the debug menu
|
||||
-F9: Pauses the emulator if the debug menu is open
|
||||
-F8: Reparses the config file while in-game
|
||||
-F7: Toggles mouse capture and mouse input
|
||||
-F6: Toggles mouse-to-gyro emulation
|
||||
|
||||
Q: How do I switch between mouse and controller joystick input? Why is it even required?
|
||||
A: Pressing F7 toggles between mouse and controller joystick input. It is required because the program polls the mouse input, which means it checks mouse movement every frame. If it didn't move, the code would manually set the emulator's virtual controller to 0 (to the center), even if other input devices would update it.
|
||||
|
||||
Q: What happens if I accidentally make a typo in the config?
|
||||
A: The code recognises the line as wrong and skips it, so the rest of the file will get parsed, but that line in question will be treated like a comment line. You can find these lines in the log if you search for 'input_handler'.
|
||||
|
||||
Q: I want to bind <input> to <output>, but your code doesn't support <input>!
|
||||
A: Some keys are intentionally omitted, but if you read the bindings through, and you're sure it is not there and isn't one of the intentionally disabled ones, open an issue on https://github.com/shadps4-emu/shadPS4.
|
||||
|
||||
Q: What does default.ini do?
|
||||
A: If you're using per-game configs, it's the base from which all new games generate their config file. If you use the unified config, then default.ini is used for every game directly instead.
|
||||
|
||||
Q: What does the use Per-game Config checkbox do?
|
||||
A: It controls whether the config is loaded from CUSAXXXXX.ini for a game or from default.ini. This way, if you only want to manage one set of bindings, you can do so, but if you want to use a different setup for every game, that's possible as well.)";
|
||||
}
|
||||
|
||||
QString HelpDialog::syntax() {
|
||||
return R"(
|
||||
Below is the file format for mouse, keyboard, and controller inputs:
|
||||
@ -187,13 +158,12 @@ Keyboard:
|
||||
Numbers:
|
||||
'0', '1', ..., '9'
|
||||
Keypad:
|
||||
'kp 0', 'kp 1', ..., 'kp 9',
|
||||
'kp .', 'kp ,', 'kp /', 'kp *', 'kp -', 'kp +', 'kp =', 'kp enter'
|
||||
'kp0', 'kp1', ..., 'kp9',
|
||||
'kpperiod', 'kpcomma', 'kpslash', 'kpasterisk', 'kpminus', 'kpplus', 'kpequals', 'kpenter'
|
||||
Symbols:
|
||||
'`', '~', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '-', '_', '=', '+', '{', '}', '[', ']', '\', '|',
|
||||
';', ':', ''', '"', ',', '<', '.', '>', '/', '?'
|
||||
(See below)
|
||||
Special keys:
|
||||
'escape (text editor only)', 'printscreen', 'scrolllock', 'pausebreak',
|
||||
'escape' (text editor only), 'printscreen', 'scrolllock', 'pausebreak',
|
||||
'backspace', 'insert', 'delete', 'home', 'end', 'pgup', 'pgdown', 'tab',
|
||||
'capslock', 'enter', 'space'
|
||||
Arrow keys:
|
||||
@ -228,7 +198,38 @@ Controller:
|
||||
'l2'
|
||||
|
||||
Invalid Inputs:
|
||||
'F1-F12' are reserved for emulator-wide keybinds, and cannot be bound to controller inputs.)";
|
||||
'F1-F12' are reserved for emulator-wide keybinds, and cannot be bound to controller inputs.
|
||||
|
||||
Symbols (expanded):
|
||||
` 'grave'
|
||||
~ 'tilde'
|
||||
! 'exclamation'
|
||||
@ 'at'
|
||||
# 'hash'
|
||||
$ 'dollar'
|
||||
% 'percent'
|
||||
^ 'caret'
|
||||
& 'ampersand'
|
||||
* 'asterisk'
|
||||
( 'lparen'
|
||||
- 'minus'
|
||||
_ 'underscore'
|
||||
= 'equals'
|
||||
+ 'plus'
|
||||
[ 'lbracket'
|
||||
{ 'lbrace'
|
||||
\ 'backslash'
|
||||
| 'pipe'
|
||||
; 'semicolon'
|
||||
: 'colon'
|
||||
' 'apostrophe'
|
||||
" 'quote'
|
||||
, 'comma'
|
||||
< 'less'
|
||||
. 'period'
|
||||
> 'greater'
|
||||
/ 'slash'
|
||||
? 'question')";
|
||||
}
|
||||
|
||||
QString HelpDialog::special() {
|
||||
@ -267,3 +268,35 @@ You can find these here, with detailed comments, examples, and suggestions for m
|
||||
'mouse_gyro_roll_mode':
|
||||
Controls whether moving the mouse sideways causes a panning or a rolling motion while mouse-to-gyro emulation is active.)";
|
||||
}
|
||||
|
||||
QString HelpDialog::faq() {
|
||||
return R"(
|
||||
Q: What are the emulator-wide keybinds?
|
||||
A:
|
||||
-F12: Triggers Renderdoc capture
|
||||
-F11: Toggles fullscreen
|
||||
-F10: Toggles FPS counter
|
||||
-Ctrl+F10: Open the debug menu
|
||||
-F9: Pauses the emulator if the debug menu is open
|
||||
-F8: Reparses the config file while in-game
|
||||
-F7: Toggles mouse capture and mouse input
|
||||
-F6: Toggles mouse-to-gyro emulation
|
||||
|
||||
Q: How do I switch between mouse and controller joystick input? Why is it even required?
|
||||
A: Pressing F7 toggles between mouse and controller joystick input. It is required because the program polls the mouse input, which means it checks mouse movement every frame. If it didn't move, the code would manually set the emulator's virtual controller to 0 (to the center), even if other input devices would update it.
|
||||
|
||||
Q: What in the world is a 'grave' key?
|
||||
A: (`). It represents one of the many symbols you can bind to a key. You can find the various symbols and their names in the Bindings tab.
|
||||
|
||||
Q: What happens if I accidentally make a typo in the config?
|
||||
A: The code recognises the line as wrong and skips it, so the rest of the file will get parsed, but that line in question will be treated like a comment line. You can find these lines in the log if you search for 'input_handler'.
|
||||
|
||||
Q: I want to bind <input> to <output>, but your code doesn't support <input>!
|
||||
A: Some keys are intentionally omitted, but if you read the bindings through, and you're sure it is not there and isn't one of the intentionally disabled ones, open an issue on https://github.com/shadps4-emu/shadPS4.
|
||||
|
||||
Q: What does default.ini do?
|
||||
A: If you're using per-game configs, it's the base from which all new games generate their config file. If you use the unified config, then default.ini is used for every game directly instead.
|
||||
|
||||
Q: What does the use Per-game Config checkbox do?
|
||||
A: It controls whether the config is loaded from CUSAXXXXX.ini for a game or from default.ini. This way, if you only want to manage one set of bindings, you can do so, but if you want to use a different setup for every game, that's possible as well.)";
|
||||
}
|
@ -473,12 +473,13 @@ void MainWindow::CreateConnects() {
|
||||
});
|
||||
|
||||
connect(ui->controllerButton, &QPushButton::clicked, this, [this]() {
|
||||
auto configWindow = new ControlSettings(m_game_info, this);
|
||||
configWindow->exec();
|
||||
ControlSettings* remapWindow =
|
||||
new ControlSettings(m_game_info, isGameRunning, runningGameSerial, this);
|
||||
remapWindow->exec();
|
||||
});
|
||||
|
||||
connect(ui->keyboardButton, &QPushButton::clicked, this, [this]() {
|
||||
auto kbmWindow = new KBMSettings(m_game_info, this);
|
||||
auto kbmWindow = new KBMSettings(m_game_info, isGameRunning, runningGameSerial, this);
|
||||
kbmWindow->exec();
|
||||
});
|
||||
|
||||
@ -846,12 +847,14 @@ void MainWindow::StartGame() {
|
||||
if (m_game_list_frame->currentItem()) {
|
||||
int itemID = m_game_list_frame->currentItem()->row();
|
||||
Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin");
|
||||
runningGameSerial = m_game_info->m_games[itemID].serial;
|
||||
}
|
||||
} else if (table_mode == 1) {
|
||||
if (m_game_grid_frame->cellClicked) {
|
||||
int itemID = (m_game_grid_frame->crtRow * m_game_grid_frame->columnCnt) +
|
||||
m_game_grid_frame->crtColumn;
|
||||
Common::FS::PathToQString(gamePath, m_game_info->m_games[itemID].path / "eboot.bin");
|
||||
runningGameSerial = m_game_info->m_games[itemID].serial;
|
||||
}
|
||||
} else {
|
||||
if (m_elf_viewer->currentItem()) {
|
||||
|
@ -75,11 +75,13 @@ private:
|
||||
void PlayBackgroundMusic();
|
||||
QIcon RecolorIcon(const QIcon& icon, bool isWhite);
|
||||
void StartEmulator(std::filesystem::path);
|
||||
|
||||
bool isIconBlack = false;
|
||||
bool isTableList = true;
|
||||
bool isGameRunning = false;
|
||||
bool isWhite = false;
|
||||
bool is_paused = false;
|
||||
std::string runningGameSerial = "";
|
||||
|
||||
QActionGroup* m_icon_size_act_group = nullptr;
|
||||
QActionGroup* m_list_mode_act_group = nullptr;
|
||||
|
47
src/qt_gui/sdl_event_wrapper.cpp
Normal file
47
src/qt_gui/sdl_event_wrapper.cpp
Normal file
@ -0,0 +1,47 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "sdl_event_wrapper.h"
|
||||
|
||||
using namespace SdlEventWrapper;
|
||||
|
||||
Wrapper* Wrapper::WrapperInstance = nullptr;
|
||||
bool Wrapper::wrapperActive = false;
|
||||
|
||||
Wrapper::Wrapper(QObject* parent) : QObject(parent) {}
|
||||
|
||||
Wrapper* Wrapper::GetInstance() {
|
||||
if (WrapperInstance == nullptr) {
|
||||
WrapperInstance = new Wrapper();
|
||||
}
|
||||
return WrapperInstance;
|
||||
}
|
||||
|
||||
bool Wrapper::ProcessEvent(SDL_Event* event) {
|
||||
switch (event->type) {
|
||||
case SDL_EVENT_WINDOW_RESTORED:
|
||||
return false;
|
||||
case SDL_EVENT_WINDOW_EXPOSED:
|
||||
return false;
|
||||
case SDL_EVENT_GAMEPAD_ADDED:
|
||||
return false;
|
||||
case SDL_EVENT_GAMEPAD_REMOVED:
|
||||
return false;
|
||||
case SDL_EVENT_QUIT:
|
||||
emit SDLEvent(SDL_EVENT_QUIT, 0, 0);
|
||||
return true;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_DOWN:
|
||||
emit SDLEvent(SDL_EVENT_GAMEPAD_BUTTON_DOWN, event->gbutton.button, 0);
|
||||
return true;
|
||||
case SDL_EVENT_GAMEPAD_BUTTON_UP:
|
||||
emit SDLEvent(SDL_EVENT_GAMEPAD_BUTTON_UP, event->gbutton.button, 0);
|
||||
return true;
|
||||
case SDL_EVENT_GAMEPAD_AXIS_MOTION:
|
||||
emit SDLEvent(SDL_EVENT_GAMEPAD_AXIS_MOTION, event->gaxis.axis, event->gaxis.value);
|
||||
return true;
|
||||
// block all other SDL events while wrapper is active
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Wrapper::~Wrapper() {}
|
25
src/qt_gui/sdl_event_wrapper.h
Normal file
25
src/qt_gui/sdl_event_wrapper.h
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
#include <QObject>
|
||||
#include <SDL3/SDL_events.h>
|
||||
|
||||
namespace SdlEventWrapper {
|
||||
|
||||
class Wrapper : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit Wrapper(QObject* parent = nullptr);
|
||||
~Wrapper();
|
||||
bool ProcessEvent(SDL_Event* event);
|
||||
static Wrapper* GetInstance();
|
||||
static bool wrapperActive;
|
||||
static Wrapper* WrapperInstance;
|
||||
|
||||
signals:
|
||||
void SDLEvent(int Type, int Input, int Value);
|
||||
};
|
||||
|
||||
} // namespace SdlEventWrapper
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>استخدام إعدادات كل لُعْبَة</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>رجوع</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>الخيارات / البَدْء</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>الأزرار</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>مثلث / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>مربع / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>دائرة / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>إكس / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>النقطة العمياء للعصا اليمنى (الافتراضي: 2، الحد الأقصى: 127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>إلغاء</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>آخر تحديث</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>عارض SFO لـ </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Fes servir configuracions per cada joc</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Torna</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Opcions / Executa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Botons d'acció</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Quadrat / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Cercle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Creu / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Zona morta de la palanca dreta (per defecte:2 màxim:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Cancel·la</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Darrera actualització</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Preferit</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Visualitzador SFO per </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>Esborra dels preferits</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Afegeix a preferits</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Sidst opdateret</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Benutze Per-Game Einstellungen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Zurück</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Aktionstasten</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Dreieck / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Quadrat / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Kreis / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Kreuz / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Rechter Stick tote Zone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Abbrechen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Zuletzt aktualisiert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO-Betrachter für </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Τελευταία ενημέρωση</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished"></translation>
|
||||
@ -565,6 +525,72 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Usar configuraciones por juego</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1/LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2/LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1/RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2/RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options/Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Botones de acción</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triángulo/Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Cuadrado/X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Círculo/B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Cruz / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Zona muerta del stick derecho (defecto: 2, máx.: 127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Cancelar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Última actualización</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Visualizador de SFO para </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>از پیکربندیهای مخصوص هر بازی استفاده کنید</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>مثلث / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>آخرین بهروزرسانی</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO مشاهده </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Käytä pelikohtaisia asetuksia</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Etunäppäimet</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Kolmio / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Neliö / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Ympyrä / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Rasti / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Oikean Analogin Deadzone (oletus:2 max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Peruuta</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Viimeksi päivitetty</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Utiliser les configurations par jeu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Retour</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Touches d'action</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Carré / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Rond / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Croix / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Joystick Gauche Deadzone (def:2 max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Annuler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Dernière mise à jour</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Visionneuse SFO pour </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Utoljára frissítve</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Terakhir diperbarui</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Usa configurazioni per gioco</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Indietro</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Opzioni / Avvio</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Pulsanti Frontali</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triangolo / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Quadrato / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Cerchio / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Croce / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Zona Morta Levetta Destra (def:2 max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Annulla</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Ultimo aggiornamento</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Visualizzatore SFO per </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>戻る</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>三角 / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>四角 / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>丸 / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>バツ / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>右スティックデッドゾーン(既定:2, 最大:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>キャンセル</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>最終更新</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>게임 별 설정 사용</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>뒤로</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>옵션 / 시작</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>마지막 업데이트</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Atgal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Atšaukti</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Paskutinį kartą atnaujinta</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Bruk oppsett per spill</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Tilbake</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Handlingsknapper</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triangel / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Firkant / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Sirkel / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Kryss / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Høyre analog dødsone (def:2, maks:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Avbryt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Sist oppdatert</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Favoritter</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO-viser for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>Fjern fra favoritter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Legg til i favoritter</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
@ -1078,7 +1118,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>note: click Help Button/Special Keybindings for more information</source>
|
||||
<translation>Merk: Trykk på hjelpeknappen for mer informasjon</translation>
|
||||
<translation>Merk: Trykk på «Hjelp»-knappen for mer informasjon</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Face Buttons</source>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -582,7 +610,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not open the file for reading</source>
|
||||
<translation/>
|
||||
<translation type="unfinished">Could not open the file for reading</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Could not open the file for writing</source>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Laatst bijgewerkt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Użyj osobnej konfiguracji dla każdej gry</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Wstecz</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Opcje / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Przyciski akcji</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Trójkąt / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Kwadrat / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Kółko / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Krzyżyk / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Martwa strefa prawego drążka (def:2 max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Anuluj</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Ostatnia aktualizacja</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Menedżer plików SFO dla </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Usar configurações por jogo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Voltar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Botões de Ação</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triângulo / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Quadrado / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Círculo / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Cruz / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Zona Morta do Analógico Direito (Pad: 2, Máx: 127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Cancelar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation>não mapeado</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation>L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation>R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation>L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation>Opções</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation>R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation>Touchpad Esquerdo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation>Touchpad Direito</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation>Triângulo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation>Quadrado</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation>Não é possível atribuir a mesma entrada mais de uma vez. Entradas duplicadas foram atribuídas aos seguintes botões:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation>Pressione um botão</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Última atualização</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Favorito</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Visualizador de SFO para </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>Remover dos Favoritos</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Adicionar aos Favoritos</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Utilizar configurações por jogo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Voltar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Opções / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Botões Frontais</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triângulo / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Quadrado / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Círculo / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Cruz / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Zona Morta do Manípulo Direito (def: 2, max: 127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Cancelar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Última atualização</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Visualizador SFO para </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Ultima actualizare</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Использовать настройки для каждой игры</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Кнопки действий</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Треугольник / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Квадрат / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Круг / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Крест / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Мёртвая зона правого стика (по умолч:2 макс:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Отмена</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation>не назначено</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation>L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation>R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation>L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation>Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation>R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation>Тачпад слева</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation>Тачпад центр</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation>Тачпад справа</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation>Треугольник</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation>Квадрат</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation>Круг</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation>Крест</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation>Невозможно привязать уникальный ввод более одного раза. Дублированные вводы назначены на следующие кнопки:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation>Нажмите кнопку</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Последнее обновление</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Избранное</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Просмотр SFO для</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>Удалить из избранного</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Добавить в избранное</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation type="unfinished">Last updated</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Përdor konfigurime të veçanta për secilën lojë</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Mbrapa</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Butonat kryesore</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Trekëndësh / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Katror / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Rreth / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Kryq / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Zona e vdekur e levës së djathtë (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Anulo</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Përditësuar për herë të fundit</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Të Preferuarat</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Shikuesi SFO për </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>Hiq nga të Preferuarat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Shto në të Preferuarat</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
@ -1186,15 +1226,15 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
<translation>Paneli me Prekje Majtas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
<translation>Paneli me Prekje në Qendër</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
<translation>Paneli me Prekje Djathtas</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation type="unfinished">Use per-game configs</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation type="unfinished">L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation type="unfinished">L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation type="unfinished">Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation type="unfinished">R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation type="unfinished">R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation type="unfinished">L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation type="unfinished">Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation type="unfinished">R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation type="unfinished">Face Buttons</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation type="unfinished">Triangle / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation type="unfinished">Square / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation type="unfinished">Circle / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation type="unfinished">Cross / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation type="unfinished">Cancel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation type="unfinished">Last updated</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Använd konfigurationer per spel</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Bakåt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Handlingsknappar</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Triangel / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Fyrkant / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Cirkel / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Kryss / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Dödläge för höger spak (standard:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Avbryt</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Senast uppdaterad</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Favorit</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO-visare för </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>Ta bort från favoriter</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Lägg till i favoriter</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Oyuna özel yapılandırma kullan</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Geri</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Seçenekler / Başlat</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Eylem Düğmeleri</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Üçgen / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Kare / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Daire / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Çarpı / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Sağ Analog Ölü Bölgesi (varsayılan: 2, en çok: 127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>İptal</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation>atanmamış</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation>Seçenekler</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation>Üçgen</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation>Kare</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation>Yuvarlak</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation>Çarpı</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation>Aynı tuş birden fazla kez atanamaz. Aşağıdaki tuşlara birden fazla giriş atanmış:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation>Bir Düğmeye Bas</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Son güncelleme</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>Sık Kullanılan</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO Görüntüleyici: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>Favorilere Ekle</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
@ -1180,7 +1220,7 @@
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
<translation>Aynı tuş birden fazla kez atanamaz. Aşağıdaki tuşlara birden fazla giriş atanmış:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Використовувати ігрові конфігурації</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / Лівий Бампер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / Лівий Тригер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Назад</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / Правий Бампер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / Правий Тригер</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>Кнопка лівого стику</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Опції / Старт</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>Кнопка правого стику</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Лицьові кнопки</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Трикутник / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Квадрат / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Коло / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Хрест / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>Мертва зона правого стику (за замов.: 2, максимум: 127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Відмінити</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Останнє оновлення</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>Перегляд SFO </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>Cấu hình riêng cho từng game</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Quay Lại</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Tuỳ chọn / Bắt đầu</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>Nút bấm mặt trước</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>Tam giác / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>Vuông / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>Tròn / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>Chéo / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation type="unfinished">Right Stick Deadzone (def:2, max:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>Hủy</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>Cập nhật lần cuối</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -924,7 +956,7 @@
|
||||
</message>
|
||||
<message>
|
||||
<source>No log file found for this game!</source>
|
||||
<translation>!</translation>
|
||||
<translation/>
|
||||
</message>
|
||||
<message>
|
||||
<source>Failed to convert icon.</source>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation type="unfinished">SFO Viewer for </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>使用每个游戏的配置</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>功能键(动作键)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>三角 / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>方框 / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>圈 / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>叉 / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>右摇杆死区(默认:2 最大:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>最后更新</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation>收藏</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO 查看器 - </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation>从收藏中移除</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation>添加至收藏</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -453,34 +453,10 @@
|
||||
<source>Use per-game configs</source>
|
||||
<translation>使用個別遊戲組態</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1 / LB</source>
|
||||
<translation>L1 / LB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2 / LT</source>
|
||||
<translation>L2 / LT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Back</source>
|
||||
<translation>Back</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1 / RB</source>
|
||||
<translation>R1 / RB</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2 / RT</source>
|
||||
<translation>R2 / RT</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L3</source>
|
||||
<translation>L3</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options / Start</source>
|
||||
<translation>Options / Start</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R3</source>
|
||||
<translation>R3</translation>
|
||||
@ -489,22 +465,6 @@
|
||||
<source>Face Buttons</source>
|
||||
<translation>功能鍵(動作按鈕)</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle / Y</source>
|
||||
<translation>三角 / Y</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square / X</source>
|
||||
<translation>正方 / X</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle / B</source>
|
||||
<translation>圖形 / B</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross / A</source>
|
||||
<translation>交叉 / A</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Right Stick Deadzone (def:2, max:127)</source>
|
||||
<translation>右搖桿無效區域(預設:2 最大:127)</translation>
|
||||
@ -565,6 +525,74 @@
|
||||
<source>Cancel</source>
|
||||
<translation>取消</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>unmapped</source>
|
||||
<translation type="unfinished">unmapped</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L1</source>
|
||||
<translation type="unfinished">L1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R1</source>
|
||||
<translation type="unfinished">R1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>L2</source>
|
||||
<translation type="unfinished">L2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Options</source>
|
||||
<translation type="unfinished">Options</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>R2</source>
|
||||
<translation type="unfinished">R2</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Left</source>
|
||||
<translation type="unfinished">Touchpad Left</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Center</source>
|
||||
<translation type="unfinished">Touchpad Center</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Touchpad Right</source>
|
||||
<translation type="unfinished">Touchpad Right</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Triangle</source>
|
||||
<translation type="unfinished">Triangle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Square</source>
|
||||
<translation type="unfinished">Square</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Circle</source>
|
||||
<translation type="unfinished">Circle</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cross</source>
|
||||
<translation type="unfinished">Cross</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</source>
|
||||
<translation type="unfinished">Cannot bind any unique input more than once. Duplicate inputs mapped to the following buttons:
|
||||
|
||||
%1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Press a button</source>
|
||||
<translation type="unfinished">Press a button</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Move analog stick</source>
|
||||
<translation type="unfinished">Move analog stick</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>EditorDialog</name>
|
||||
@ -748,6 +776,10 @@
|
||||
<source>Last updated</source>
|
||||
<translation>最後更新</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Favorite</source>
|
||||
<translation type="unfinished">Favorite</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>GameListUtils</name>
|
||||
@ -950,6 +982,14 @@
|
||||
<source>SFO Viewer for </source>
|
||||
<translation>SFO 檢視器: </translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Remove from Favorites</source>
|
||||
<translation type="unfinished">Remove from Favorites</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Add to Favorites</source>
|
||||
<translation type="unfinished">Add to Favorites</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>HelpDialog</name>
|
||||
|
@ -20,6 +20,10 @@
|
||||
#include "sdl_window.h"
|
||||
#include "video_core/renderdoc.h"
|
||||
|
||||
#ifdef ENABLE_QT_GUI
|
||||
#include "qt_gui/sdl_event_wrapper.h"
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include "SDL3/SDL_metal.h"
|
||||
#endif
|
||||
@ -340,6 +344,13 @@ void WindowSDL::WaitEvent() {
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_QT_GUI
|
||||
if (SdlEventWrapper::Wrapper::wrapperActive) {
|
||||
if (SdlEventWrapper::Wrapper::GetInstance()->ProcessEvent(&event))
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ImGui::Core::ProcessEvent(&event)) {
|
||||
return;
|
||||
}
|
||||
|
@ -300,7 +300,7 @@ void SetupCapabilities(const Info& info, const Profile& profile, EmitContext& ct
|
||||
if (stage == LogicalStage::TessellationControl || stage == LogicalStage::TessellationEval) {
|
||||
ctx.AddCapability(spv::Capability::Tessellation);
|
||||
}
|
||||
if (info.dma_types != IR::Type::Void) {
|
||||
if (info.uses_dma) {
|
||||
ctx.AddCapability(spv::Capability::PhysicalStorageBufferAddresses);
|
||||
ctx.AddExtension("SPV_KHR_physical_storage_buffer");
|
||||
}
|
||||
|
@ -7,7 +7,11 @@
|
||||
#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
|
||||
|
||||
namespace Shader::Backend::SPIRV {
|
||||
|
||||
namespace {
|
||||
using PointerType = EmitContext::PointerType;
|
||||
using PointerSize = EmitContext::PointerSize;
|
||||
|
||||
std::pair<Id, Id> AtomicArgs(EmitContext& ctx) {
|
||||
const Id scope{ctx.ConstU32(static_cast<u32>(spv::Scope::Device))};
|
||||
const Id semantics{ctx.u32_zero_value};
|
||||
@ -61,14 +65,13 @@ Id BufferAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id
|
||||
return ctx.U32[1];
|
||||
}
|
||||
}();
|
||||
if (Sirit::ValidId(buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
|
||||
if (const Id offset = buffer.Offset(PointerSize::B32); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
|
||||
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U32];
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index);
|
||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address);
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return AccessBoundsCheck<32, 1, is_float>(ctx, index, buffer.size_dwords, [&] {
|
||||
return AccessBoundsCheck<32, 1, is_float>(ctx, address, buffer.Size(PointerSize::B32), [&] {
|
||||
return (ctx.*atomic_func)(type, ptr, scope, semantics, value);
|
||||
});
|
||||
}
|
||||
@ -76,14 +79,13 @@ Id BufferAtomicU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id
|
||||
Id BufferAtomicU32IncDec(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address,
|
||||
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id)) {
|
||||
const auto& buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
|
||||
if (const Id offset = buffer.Offset(PointerSize::B32); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
|
||||
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U32];
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index);
|
||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address);
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return AccessBoundsCheck<32>(ctx, index, buffer.size_dwords, [&] {
|
||||
return AccessBoundsCheck<32>(ctx, address, buffer.Size(PointerSize::B32), [&] {
|
||||
return (ctx.*atomic_func)(ctx.U32[1], ptr, scope, semantics);
|
||||
});
|
||||
}
|
||||
@ -92,14 +94,13 @@ Id BufferAtomicU32CmpSwap(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre
|
||||
Id cmp_value,
|
||||
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id, Id, Id)) {
|
||||
const auto& buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
|
||||
if (const Id offset = buffer.Offset(PointerSize::B32); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
|
||||
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U32];
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index);
|
||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address);
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return AccessBoundsCheck<32>(ctx, index, buffer.size_dwords, [&] {
|
||||
return AccessBoundsCheck<32>(ctx, address, buffer.Size(PointerSize::B32), [&] {
|
||||
return (ctx.*atomic_func)(ctx.U32[1], ptr, scope, semantics, semantics, value, cmp_value);
|
||||
});
|
||||
}
|
||||
@ -107,14 +108,13 @@ Id BufferAtomicU32CmpSwap(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre
|
||||
Id BufferAtomicU64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address, Id value,
|
||||
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
|
||||
const auto& buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, buffer.offset);
|
||||
if (const Id offset = buffer.Offset(PointerSize::B64); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(3u));
|
||||
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U64];
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index);
|
||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U64);
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address);
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return AccessBoundsCheck<64>(ctx, index, buffer.size_qwords, [&] {
|
||||
return AccessBoundsCheck<64>(ctx, address, buffer.Size(PointerSize::B64), [&] {
|
||||
return (ctx.*atomic_func)(ctx.U64, ptr, scope, semantics, value);
|
||||
});
|
||||
}
|
||||
@ -360,7 +360,7 @@ Id EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id co
|
||||
|
||||
Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding) {
|
||||
const auto& buffer = ctx.buffers[binding];
|
||||
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U32];
|
||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, ctx.ConstU32(gds_addr));
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return ctx.OpAtomicIIncrement(ctx.U32[1], ptr, scope, semantics);
|
||||
@ -368,7 +368,7 @@ Id EmitDataAppend(EmitContext& ctx, u32 gds_addr, u32 binding) {
|
||||
|
||||
Id EmitDataConsume(EmitContext& ctx, u32 gds_addr, u32 binding) {
|
||||
const auto& buffer = ctx.buffers[binding];
|
||||
const auto [id, pointer_type] = buffer[EmitContext::PointerType::U32];
|
||||
const auto [id, pointer_type] = buffer.Alias(PointerType::U32);
|
||||
const Id ptr = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, ctx.ConstU32(gds_addr));
|
||||
const auto [scope, semantics]{AtomicArgs(ctx)};
|
||||
return ctx.OpAtomicIDecrement(ctx.U32[1], ptr, scope, semantics);
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "shader_recompiler/backend/spirv/emit_spirv_bounds.h"
|
||||
#include "shader_recompiler/backend/spirv/emit_spirv_instructions.h"
|
||||
#include "shader_recompiler/backend/spirv/spirv_emit_context.h"
|
||||
#include "shader_recompiler/ir/attribute.h"
|
||||
@ -11,8 +12,6 @@
|
||||
|
||||
#include <magic_enum/magic_enum.hpp>
|
||||
|
||||
#include "emit_spirv_bounds.h"
|
||||
|
||||
namespace Shader::Backend::SPIRV {
|
||||
namespace {
|
||||
|
||||
@ -164,6 +163,7 @@ void EmitGetGotoVariable(EmitContext&) {
|
||||
}
|
||||
|
||||
using PointerType = EmitContext::PointerType;
|
||||
using PointerSize = EmitContext::PointerSize;
|
||||
|
||||
Id EmitReadConst(EmitContext& ctx, IR::Inst* inst, Id addr, Id offset) {
|
||||
const u32 flatbuf_off_dw = inst->Flags<u32>();
|
||||
@ -179,14 +179,15 @@ Id EmitReadConst(EmitContext& ctx, IR::Inst* inst, Id addr, Id offset) {
|
||||
template <PointerType type>
|
||||
Id ReadConstBuffer(EmitContext& ctx, u32 handle, Id index) {
|
||||
const auto& buffer = ctx.buffers[handle];
|
||||
index = ctx.OpIAdd(ctx.U32[1], index, buffer.offset_dwords);
|
||||
const auto [id, pointer_type] = buffer[type];
|
||||
if (const Id offset = buffer.Offset(PointerSize::B32); Sirit::ValidId(offset)) {
|
||||
index = ctx.OpIAdd(ctx.U32[1], index, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = buffer.Alias(type);
|
||||
const auto value_type = type == PointerType::U32 ? ctx.U32[1] : ctx.F32[1];
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)};
|
||||
const Id result{ctx.OpLoad(value_type, ptr)};
|
||||
|
||||
if (Sirit::ValidId(buffer.size_dwords)) {
|
||||
const Id in_bounds = ctx.OpULessThan(ctx.U1[1], index, buffer.size_dwords);
|
||||
if (const Id size = buffer.Size(PointerSize::B32); Sirit::ValidId(size)) {
|
||||
const Id in_bounds = ctx.OpULessThan(ctx.U1[1], index, size);
|
||||
return ctx.OpSelect(value_type, in_bounds, result, ctx.u32_zero_value);
|
||||
}
|
||||
return result;
|
||||
@ -419,25 +420,24 @@ void EmitSetPatch(EmitContext& ctx, IR::Patch patch, Id value) {
|
||||
|
||||
template <u32 N, PointerType alias>
|
||||
static Id EmitLoadBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
constexpr bool is_float = alias == PointerType::F32;
|
||||
const auto flags = inst->Flags<IR::BufferInstInfo>();
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B32); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
|
||||
const auto& data_types = alias == PointerType::U32 ? ctx.U32 : ctx.F32;
|
||||
const auto [id, pointer_type] = spv_buffer[alias];
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(alias);
|
||||
|
||||
boost::container::static_vector<Id, N> ids;
|
||||
for (u32 i = 0; i < N; i++) {
|
||||
const Id index_i = i == 0 ? index : ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i));
|
||||
const Id index_i = i == 0 ? address : ctx.OpIAdd(ctx.U32[1], address, ctx.ConstU32(i));
|
||||
const Id ptr_i = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i);
|
||||
const Id result_i = ctx.OpLoad(data_types[1], ptr_i);
|
||||
if (!flags.typed) {
|
||||
// Untyped loads have bounds checking per-component.
|
||||
ids.push_back(LoadAccessBoundsCheck < 32, 1,
|
||||
alias ==
|
||||
PointerType::F32 > (ctx, index_i, spv_buffer.size_dwords, result_i));
|
||||
ids.push_back(LoadAccessBoundsCheck<32, 1, is_float>(
|
||||
ctx, index_i, spv_buffer.Size(PointerSize::B32), result_i));
|
||||
} else {
|
||||
ids.push_back(result_i);
|
||||
}
|
||||
@ -446,33 +446,32 @@ static Id EmitLoadBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id a
|
||||
const Id result = N == 1 ? ids[0] : ctx.OpCompositeConstruct(data_types[N], ids);
|
||||
if (flags.typed) {
|
||||
// Typed loads have single bounds check for the whole load.
|
||||
return LoadAccessBoundsCheck < 32, N,
|
||||
alias == PointerType::F32 > (ctx, index, spv_buffer.size_dwords, result);
|
||||
return LoadAccessBoundsCheck<32, N, is_float>(ctx, address,
|
||||
spv_buffer.Size(PointerSize::B32), result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Id EmitLoadBufferU8(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B8); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = spv_buffer[PointerType::U8];
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(PointerType::U8);
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)};
|
||||
const Id result{ctx.OpLoad(ctx.U8, ptr)};
|
||||
return LoadAccessBoundsCheck<8>(ctx, address, spv_buffer.size, result);
|
||||
return LoadAccessBoundsCheck<8>(ctx, address, spv_buffer.Size(PointerSize::B8), result);
|
||||
}
|
||||
|
||||
Id EmitLoadBufferU16(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B16); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = spv_buffer[PointerType::U16];
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(1u));
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)};
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(PointerType::U16);
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)};
|
||||
const Id result{ctx.OpLoad(ctx.U16, ptr)};
|
||||
return LoadAccessBoundsCheck<16>(ctx, index, spv_buffer.size_shorts, result);
|
||||
return LoadAccessBoundsCheck<16>(ctx, address, spv_buffer.Size(PointerSize::B16), result);
|
||||
}
|
||||
|
||||
Id EmitLoadBufferU32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
@ -493,14 +492,13 @@ Id EmitLoadBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address)
|
||||
|
||||
Id EmitLoadBufferU64(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B64); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = spv_buffer[PointerType::U64];
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(3u));
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u64_zero_value, index)};
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(PointerType::U64);
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u64_zero_value, address)};
|
||||
const Id result{ctx.OpLoad(ctx.U64, ptr)};
|
||||
return LoadAccessBoundsCheck<64>(ctx, index, spv_buffer.size_qwords, result);
|
||||
return LoadAccessBoundsCheck<64>(ctx, address, spv_buffer.Size(PointerSize::B64), result);
|
||||
}
|
||||
|
||||
Id EmitLoadBufferF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address) {
|
||||
@ -526,18 +524,18 @@ Id EmitLoadBufferFormatF32(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addr
|
||||
template <u32 N, PointerType alias>
|
||||
static void EmitStoreBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, Id address,
|
||||
Id value) {
|
||||
constexpr bool is_float = alias == PointerType::F32;
|
||||
const auto flags = inst->Flags<IR::BufferInstInfo>();
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B32); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(2u));
|
||||
const auto& data_types = alias == PointerType::U32 ? ctx.U32 : ctx.F32;
|
||||
const auto [id, pointer_type] = spv_buffer[alias];
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(alias);
|
||||
|
||||
auto store = [&] {
|
||||
for (u32 i = 0; i < N; i++) {
|
||||
const Id index_i = i == 0 ? index : ctx.OpIAdd(ctx.U32[1], index, ctx.ConstU32(i));
|
||||
const Id index_i = i == 0 ? address : ctx.OpIAdd(ctx.U32[1], address, ctx.ConstU32(i));
|
||||
const Id ptr_i = ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index_i);
|
||||
const Id value_i = N == 1 ? value : ctx.OpCompositeExtract(data_types[1], value, i);
|
||||
auto store_i = [&] {
|
||||
@ -546,8 +544,8 @@ static void EmitStoreBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, I
|
||||
};
|
||||
if (!flags.typed) {
|
||||
// Untyped stores have bounds checking per-component.
|
||||
AccessBoundsCheck<32, 1, alias == PointerType::F32>(
|
||||
ctx, index_i, spv_buffer.size_dwords, store_i);
|
||||
AccessBoundsCheck<32, 1, is_float>(ctx, index_i, spv_buffer.Size(PointerSize::B32),
|
||||
store_i);
|
||||
} else {
|
||||
store_i();
|
||||
}
|
||||
@ -557,8 +555,7 @@ static void EmitStoreBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, I
|
||||
|
||||
if (flags.typed) {
|
||||
// Typed stores have single bounds check for the whole store.
|
||||
AccessBoundsCheck<32, N, alias == PointerType::F32>(ctx, index, spv_buffer.size_dwords,
|
||||
store);
|
||||
AccessBoundsCheck<32, N, is_float>(ctx, address, spv_buffer.Size(PointerSize::B32), store);
|
||||
} else {
|
||||
store();
|
||||
}
|
||||
@ -566,12 +563,12 @@ static void EmitStoreBufferB32xN(EmitContext& ctx, IR::Inst* inst, u32 handle, I
|
||||
|
||||
void EmitStoreBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B8); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = spv_buffer[PointerType::U8];
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(PointerType::U8);
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)};
|
||||
AccessBoundsCheck<8>(ctx, address, spv_buffer.size, [&] {
|
||||
AccessBoundsCheck<8>(ctx, address, spv_buffer.Size(PointerSize::B8), [&] {
|
||||
ctx.OpStore(ptr, value);
|
||||
return Id{};
|
||||
});
|
||||
@ -579,13 +576,12 @@ void EmitStoreBufferU8(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id v
|
||||
|
||||
void EmitStoreBufferU16(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B16); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = spv_buffer[PointerType::U16];
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(1u));
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, index)};
|
||||
AccessBoundsCheck<16>(ctx, index, spv_buffer.size_shorts, [&] {
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(PointerType::U16);
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u32_zero_value, address)};
|
||||
AccessBoundsCheck<16>(ctx, address, spv_buffer.Size(PointerSize::B16), [&] {
|
||||
ctx.OpStore(ptr, value);
|
||||
return Id{};
|
||||
});
|
||||
@ -609,13 +605,12 @@ void EmitStoreBufferU32x4(EmitContext& ctx, IR::Inst* inst, u32 handle, Id addre
|
||||
|
||||
void EmitStoreBufferU64(EmitContext& ctx, IR::Inst*, u32 handle, Id address, Id value) {
|
||||
const auto& spv_buffer = ctx.buffers[handle];
|
||||
if (Sirit::ValidId(spv_buffer.offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, spv_buffer.offset);
|
||||
if (const Id offset = spv_buffer.Offset(PointerSize::B64); Sirit::ValidId(offset)) {
|
||||
address = ctx.OpIAdd(ctx.U32[1], address, offset);
|
||||
}
|
||||
const auto [id, pointer_type] = spv_buffer[PointerType::U64];
|
||||
const Id index = ctx.OpShiftRightLogical(ctx.U32[1], address, ctx.ConstU32(3u));
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u64_zero_value, index)};
|
||||
AccessBoundsCheck<64>(ctx, index, spv_buffer.size_qwords, [&] {
|
||||
const auto [id, pointer_type] = spv_buffer.Alias(PointerType::U64);
|
||||
const Id ptr{ctx.OpAccessChain(pointer_type, id, ctx.u64_zero_value, address)};
|
||||
AccessBoundsCheck<64>(ctx, address, spv_buffer.Size(PointerSize::B64), [&] {
|
||||
ctx.OpStore(ptr, value);
|
||||
return Id{};
|
||||
});
|
||||
|
@ -71,7 +71,7 @@ EmitContext::EmitContext(const Profile& profile_, const RuntimeInfo& runtime_inf
|
||||
Bindings& binding_)
|
||||
: Sirit::Module(profile_.supported_spirv), info{info_}, runtime_info{runtime_info_},
|
||||
profile{profile_}, stage{info.stage}, l_stage{info.l_stage}, binding{binding_} {
|
||||
if (info.dma_types != IR::Type::Void) {
|
||||
if (info.uses_dma) {
|
||||
SetMemoryModel(spv::AddressingModel::PhysicalStorageBuffer64, spv::MemoryModel::GLSL450);
|
||||
} else {
|
||||
SetMemoryModel(spv::AddressingModel::Logical, spv::MemoryModel::GLSL450);
|
||||
@ -169,34 +169,8 @@ void EmitContext::DefineArithmeticTypes() {
|
||||
if (info.uses_fp64) {
|
||||
frexp_result_f64 = Name(TypeStruct(F64[1], S32[1]), "frexp_result_f64");
|
||||
}
|
||||
|
||||
if (True(info.dma_types & IR::Type::F64)) {
|
||||
physical_pointer_types[PointerType::F64] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, F64[1]);
|
||||
}
|
||||
if (True(info.dma_types & IR::Type::U64)) {
|
||||
physical_pointer_types[PointerType::U64] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, U64);
|
||||
}
|
||||
if (True(info.dma_types & IR::Type::F32)) {
|
||||
physical_pointer_types[PointerType::F32] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, F32[1]);
|
||||
}
|
||||
if (True(info.dma_types & IR::Type::U32)) {
|
||||
physical_pointer_types[PointerType::U32] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, U32[1]);
|
||||
}
|
||||
if (True(info.dma_types & IR::Type::F16)) {
|
||||
physical_pointer_types[PointerType::F16] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, F16[1]);
|
||||
}
|
||||
if (True(info.dma_types & IR::Type::U16)) {
|
||||
physical_pointer_types[PointerType::U16] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, U16);
|
||||
}
|
||||
if (True(info.dma_types & IR::Type::U8)) {
|
||||
physical_pointer_types[PointerType::U8] =
|
||||
TypePointer(spv::StorageClass::PhysicalStorageBuffer, U8);
|
||||
if (info.uses_dma) {
|
||||
physical_pointer_type_u32 = TypePointer(spv::StorageClass::PhysicalStorageBuffer, U32[1]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -239,7 +213,7 @@ Id EmitContext::GetBufferSize(const u32 sharp_idx) {
|
||||
// Can this be done with memory access? Like we do now with ReadConst
|
||||
const auto& srt_flatbuf = buffers[flatbuf_index];
|
||||
ASSERT(srt_flatbuf.buffer_type == BufferType::Flatbuf);
|
||||
const auto [id, pointer_type] = srt_flatbuf[PointerType::U32];
|
||||
const auto [id, pointer_type] = srt_flatbuf.Alias(PointerType::U32);
|
||||
|
||||
const auto rsrc1{
|
||||
OpLoad(U32[1], OpAccessChain(pointer_type, id, u32_zero_value, ConstU32(sharp_idx + 1)))};
|
||||
@ -255,39 +229,70 @@ Id EmitContext::GetBufferSize(const u32 sharp_idx) {
|
||||
}
|
||||
|
||||
void EmitContext::DefineBufferProperties() {
|
||||
if (!profile.needs_buffer_offsets && profile.supports_robust_buffer_access) {
|
||||
return;
|
||||
}
|
||||
for (u32 i = 0; i < buffers.size(); i++) {
|
||||
BufferDefinition& buffer = buffers[i];
|
||||
auto& buffer = buffers[i];
|
||||
const auto& desc = info.buffers[i];
|
||||
const u32 binding = buffer.binding;
|
||||
if (buffer.buffer_type != BufferType::Guest) {
|
||||
continue;
|
||||
}
|
||||
const u32 binding = buffer.binding;
|
||||
const u32 half = PushData::BufOffsetIndex + (binding >> 4);
|
||||
const u32 comp = (binding & 0xf) >> 2;
|
||||
const u32 offset = (binding & 0x3) << 3;
|
||||
const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]),
|
||||
push_data_block, ConstU32(half), ConstU32(comp))};
|
||||
const Id value{OpLoad(U32[1], ptr)};
|
||||
buffer.offset = OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U));
|
||||
Name(buffer.offset, fmt::format("buf{}_off", binding));
|
||||
buffer.offset_dwords = OpShiftRightLogical(U32[1], buffer.offset, ConstU32(2U));
|
||||
Name(buffer.offset_dwords, fmt::format("buf{}_dword_off", binding));
|
||||
|
||||
// Only need to load size if performing bounds checks and the buffer is both guest and not
|
||||
// inline.
|
||||
if (!profile.supports_robust_buffer_access && buffer.buffer_type == BufferType::Guest) {
|
||||
const BufferResource& desc = info.buffers[i];
|
||||
if (desc.sharp_idx == std::numeric_limits<u32>::max()) {
|
||||
buffer.size = ConstU32(desc.inline_cbuf.GetSize());
|
||||
} else {
|
||||
buffer.size = GetBufferSize(desc.sharp_idx);
|
||||
// Only load and apply buffer offsets if host GPU alignment is larger than guest.
|
||||
if (profile.needs_buffer_offsets) {
|
||||
const u32 half = PushData::BufOffsetIndex + (binding >> 4);
|
||||
const u32 comp = (binding & 0xf) >> 2;
|
||||
const u32 offset = (binding & 0x3) << 3;
|
||||
const Id ptr{OpAccessChain(TypePointer(spv::StorageClass::PushConstant, U32[1]),
|
||||
push_data_block, ConstU32(half), ConstU32(comp))};
|
||||
const Id value{OpLoad(U32[1], ptr)};
|
||||
|
||||
const Id buf_offset{OpBitFieldUExtract(U32[1], value, ConstU32(offset), ConstU32(8U))};
|
||||
Name(buf_offset, fmt::format("buf{}_off", binding));
|
||||
buffer.Offset(PointerSize::B8) = buf_offset;
|
||||
|
||||
if (True(desc.used_types & IR::Type::U16)) {
|
||||
const Id buf_word_offset{OpShiftRightLogical(U32[1], buf_offset, ConstU32(1U))};
|
||||
Name(buf_word_offset, fmt::format("buf{}_word_off", binding));
|
||||
buffer.Offset(PointerSize::B16) = buf_word_offset;
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U32)) {
|
||||
const Id buf_dword_offset{OpShiftRightLogical(U32[1], buf_offset, ConstU32(2U))};
|
||||
Name(buf_dword_offset, fmt::format("buf{}_dword_off", binding));
|
||||
buffer.Offset(PointerSize::B32) = buf_dword_offset;
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U64)) {
|
||||
const Id buf_qword_offset{OpShiftRightLogical(U32[1], buf_offset, ConstU32(3U))};
|
||||
Name(buf_qword_offset, fmt::format("buf{}_qword_off", binding));
|
||||
buffer.Offset(PointerSize::B64) = buf_qword_offset;
|
||||
}
|
||||
}
|
||||
|
||||
// Only load size if performing bounds checks.
|
||||
if (!profile.supports_robust_buffer_access) {
|
||||
const Id buf_size{desc.sharp_idx == std::numeric_limits<u32>::max()
|
||||
? ConstU32(desc.inline_cbuf.GetSize())
|
||||
: GetBufferSize(desc.sharp_idx)};
|
||||
Name(buf_size, fmt::format("buf{}_size", binding));
|
||||
buffer.Size(PointerSize::B8) = buf_size;
|
||||
|
||||
if (True(desc.used_types & IR::Type::U16)) {
|
||||
const Id buf_word_size{OpShiftRightLogical(U32[1], buf_size, ConstU32(1U))};
|
||||
Name(buf_word_size, fmt::format("buf{}_short_size", binding));
|
||||
buffer.Size(PointerSize::B16) = buf_word_size;
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U32)) {
|
||||
const Id buf_dword_size{OpShiftRightLogical(U32[1], buf_size, ConstU32(2U))};
|
||||
Name(buf_dword_size, fmt::format("buf{}_dword_size", binding));
|
||||
buffer.Size(PointerSize::B32) = buf_dword_size;
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U64)) {
|
||||
const Id buf_qword_size{OpShiftRightLogical(U32[1], buf_size, ConstU32(3U))};
|
||||
Name(buf_qword_size, fmt::format("buf{}_qword_size", binding));
|
||||
buffer.Size(PointerSize::B64) = buf_qword_size;
|
||||
}
|
||||
Name(buffer.size, fmt::format("buf{}_size", binding));
|
||||
buffer.size_shorts = OpShiftRightLogical(U32[1], buffer.size, ConstU32(1U));
|
||||
Name(buffer.size_shorts, fmt::format("buf{}_short_size", binding));
|
||||
buffer.size_dwords = OpShiftRightLogical(U32[1], buffer.size, ConstU32(2U));
|
||||
Name(buffer.size_dwords, fmt::format("buf{}_dword_size", binding));
|
||||
buffer.size_qwords = OpShiftRightLogical(U32[1], buffer.size, ConstU32(3U));
|
||||
Name(buffer.size_qwords, fmt::format("buf{}_qword_size", binding));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -779,8 +784,7 @@ EmitContext::BufferSpv EmitContext::DefineBuffer(bool is_storage, bool is_writte
|
||||
};
|
||||
|
||||
void EmitContext::DefineBuffers() {
|
||||
if (!profile.supports_robust_buffer_access &&
|
||||
info.readconst_types == Info::ReadConstType::None) {
|
||||
if (!profile.supports_robust_buffer_access && !info.uses_dma) {
|
||||
// In case Flatbuf has not already been bound by IR and is needed
|
||||
// to query buffer sizes, bind it now.
|
||||
info.buffers.push_back({
|
||||
@ -809,23 +813,23 @@ void EmitContext::DefineBuffers() {
|
||||
// Define aliases depending on the shader usage.
|
||||
auto& spv_buffer = buffers.emplace_back(binding.buffer++, desc.buffer_type);
|
||||
if (True(desc.used_types & IR::Type::U64)) {
|
||||
spv_buffer[PointerType::U64] =
|
||||
spv_buffer.Alias(PointerType::U64) =
|
||||
DefineBuffer(is_storage, desc.is_written, 3, desc.buffer_type, U64);
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U32)) {
|
||||
spv_buffer[PointerType::U32] =
|
||||
spv_buffer.Alias(PointerType::U32) =
|
||||
DefineBuffer(is_storage, desc.is_written, 2, desc.buffer_type, U32[1]);
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::F32)) {
|
||||
spv_buffer[PointerType::F32] =
|
||||
spv_buffer.Alias(PointerType::F32) =
|
||||
DefineBuffer(is_storage, desc.is_written, 2, desc.buffer_type, F32[1]);
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U16)) {
|
||||
spv_buffer[PointerType::U16] =
|
||||
spv_buffer.Alias(PointerType::U16) =
|
||||
DefineBuffer(is_storage, desc.is_written, 1, desc.buffer_type, U16);
|
||||
}
|
||||
if (True(desc.used_types & IR::Type::U8)) {
|
||||
spv_buffer[PointerType::U8] =
|
||||
spv_buffer.Alias(PointerType::U8) =
|
||||
DefineBuffer(is_storage, desc.is_written, 0, desc.buffer_type, U8);
|
||||
}
|
||||
++binding.unified;
|
||||
@ -1154,7 +1158,7 @@ Id EmitContext::DefineGetBdaPointer() {
|
||||
const auto page{OpShiftRightLogical(U64, address, caching_pagebits)};
|
||||
const auto page32{OpUConvert(U32[1], page)};
|
||||
const auto& bda_buffer{buffers[bda_pagetable_index]};
|
||||
const auto [bda_buffer_id, bda_pointer_type] = bda_buffer[PointerType::U64];
|
||||
const auto [bda_buffer_id, bda_pointer_type] = bda_buffer.Alias(PointerType::U64);
|
||||
const auto bda_ptr{OpAccessChain(bda_pointer_type, bda_buffer_id, u32_zero_value, page32)};
|
||||
const auto bda{OpLoad(U64, bda_ptr)};
|
||||
|
||||
@ -1166,14 +1170,14 @@ Id EmitContext::DefineGetBdaPointer() {
|
||||
// First time acces, mark as fault
|
||||
AddLabel(fault_label);
|
||||
const auto& fault_buffer{buffers[fault_buffer_index]};
|
||||
const auto [fault_buffer_id, fault_pointer_type] = fault_buffer[PointerType::U8];
|
||||
const auto page_div8{OpShiftRightLogical(U32[1], page32, ConstU32(3U))};
|
||||
const auto page_mod8{OpBitwiseAnd(U32[1], page32, ConstU32(7U))};
|
||||
const auto page_mask{OpShiftLeftLogical(U8, u8_one_value, page_mod8)};
|
||||
const auto [fault_buffer_id, fault_pointer_type] = fault_buffer.Alias(PointerType::U32);
|
||||
const auto page_div32{OpShiftRightLogical(U32[1], page32, ConstU32(5U))};
|
||||
const auto page_mod32{OpBitwiseAnd(U32[1], page32, ConstU32(31U))};
|
||||
const auto page_mask{OpShiftLeftLogical(U32[1], u32_one_value, page_mod32)};
|
||||
const auto fault_ptr{
|
||||
OpAccessChain(fault_pointer_type, fault_buffer_id, u32_zero_value, page_div8)};
|
||||
const auto fault_value{OpLoad(U8, fault_ptr)};
|
||||
const auto fault_value_masked{OpBitwiseOr(U8, fault_value, page_mask)};
|
||||
OpAccessChain(fault_pointer_type, fault_buffer_id, u32_zero_value, page_div32)};
|
||||
const auto fault_value{OpLoad(U32[1], fault_ptr)};
|
||||
const auto fault_value_masked{OpBitwiseOr(U32[1], fault_value, page_mask)};
|
||||
OpStore(fault_ptr, fault_value_masked);
|
||||
|
||||
// Return null pointer
|
||||
@ -1211,14 +1215,15 @@ Id EmitContext::DefineReadConst(bool dynamic) {
|
||||
const auto offset_bytes{OpShiftLeftLogical(U32[1], offset, ConstU32(2U))};
|
||||
const auto addr{OpIAdd(U64, base_addr, OpUConvert(U64, offset_bytes))};
|
||||
|
||||
const auto result = EmitMemoryRead(U32[1], addr, [&]() {
|
||||
const auto result = EmitDwordMemoryRead(addr, [&]() {
|
||||
if (dynamic) {
|
||||
return u32_zero_value;
|
||||
} else {
|
||||
const auto& flatbuf_buffer{buffers[flatbuf_index]};
|
||||
ASSERT(flatbuf_buffer.binding >= 0 &&
|
||||
flatbuf_buffer.buffer_type == BufferType::Flatbuf);
|
||||
const auto [flatbuf_buffer_id, flatbuf_pointer_type] = flatbuf_buffer[PointerType::U32];
|
||||
const auto [flatbuf_buffer_id, flatbuf_pointer_type] =
|
||||
flatbuf_buffer.Alias(PointerType::U32);
|
||||
const auto ptr{OpAccessChain(flatbuf_pointer_type, flatbuf_buffer_id, u32_zero_value,
|
||||
flatbuf_offset)};
|
||||
return OpLoad(U32[1], ptr);
|
||||
@ -1239,7 +1244,7 @@ void EmitContext::DefineFunctions() {
|
||||
uf11_to_f32 = DefineUfloatM5ToFloat32(6, "uf11_to_f32");
|
||||
uf10_to_f32 = DefineUfloatM5ToFloat32(5, "uf10_to_f32");
|
||||
}
|
||||
if (info.dma_types != IR::Type::Void) {
|
||||
if (info.uses_dma) {
|
||||
get_bda_pointer = DefineGetBdaPointer();
|
||||
}
|
||||
|
||||
|
@ -42,17 +42,6 @@ public:
|
||||
Bindings& binding);
|
||||
~EmitContext();
|
||||
|
||||
enum class PointerType : u32 {
|
||||
U8,
|
||||
U16,
|
||||
F16,
|
||||
U32,
|
||||
F32,
|
||||
U64,
|
||||
F64,
|
||||
NumAlias,
|
||||
};
|
||||
|
||||
Id Def(const IR::Value& value);
|
||||
|
||||
void DefineBufferProperties();
|
||||
@ -155,25 +144,7 @@ public:
|
||||
return last_label;
|
||||
}
|
||||
|
||||
PointerType PointerTypeFromType(Id type) {
|
||||
if (type.value == U8.value)
|
||||
return PointerType::U8;
|
||||
if (type.value == U16.value)
|
||||
return PointerType::U16;
|
||||
if (type.value == F16[1].value)
|
||||
return PointerType::F16;
|
||||
if (type.value == U32[1].value)
|
||||
return PointerType::U32;
|
||||
if (type.value == F32[1].value)
|
||||
return PointerType::F32;
|
||||
if (type.value == U64.value)
|
||||
return PointerType::U64;
|
||||
if (type.value == F64[1].value)
|
||||
return PointerType::F64;
|
||||
UNREACHABLE_MSG("Unknown type for pointer");
|
||||
}
|
||||
|
||||
Id EmitMemoryRead(Id type, Id address, auto&& fallback) {
|
||||
Id EmitDwordMemoryRead(Id address, auto&& fallback) {
|
||||
const Id available_label = OpLabel();
|
||||
const Id fallback_label = OpLabel();
|
||||
const Id merge_label = OpLabel();
|
||||
@ -185,10 +156,8 @@ public:
|
||||
|
||||
// Available
|
||||
AddLabel(available_label);
|
||||
const auto pointer_type = PointerTypeFromType(type);
|
||||
const Id pointer_type_id = physical_pointer_types[pointer_type];
|
||||
const Id addr_ptr = OpConvertUToPtr(pointer_type_id, addr);
|
||||
const Id result = OpLoad(type, addr_ptr, spv::MemoryAccessMask::Aligned, 4u);
|
||||
const Id addr_ptr = OpConvertUToPtr(physical_pointer_type_u32, addr);
|
||||
const Id result = OpLoad(U32[1], addr_ptr, spv::MemoryAccessMask::Aligned, 4u);
|
||||
OpBranch(merge_label);
|
||||
|
||||
// Fallback
|
||||
@ -199,7 +168,7 @@ public:
|
||||
// Merge
|
||||
AddLabel(merge_label);
|
||||
const Id final_result =
|
||||
OpPhi(type, fallback_result, fallback_label, result, available_label);
|
||||
OpPhi(U32[1], fallback_result, fallback_label, result, available_label);
|
||||
return final_result;
|
||||
}
|
||||
|
||||
@ -314,6 +283,24 @@ public:
|
||||
bool is_storage = false;
|
||||
};
|
||||
|
||||
enum class PointerType : u32 {
|
||||
U8,
|
||||
U16,
|
||||
U32,
|
||||
F32,
|
||||
U64,
|
||||
F64,
|
||||
NumAlias,
|
||||
};
|
||||
|
||||
enum class PointerSize : u32 {
|
||||
B8,
|
||||
B16,
|
||||
B32,
|
||||
B64,
|
||||
NumClass,
|
||||
};
|
||||
|
||||
struct BufferSpv {
|
||||
Id id;
|
||||
Id pointer_type;
|
||||
@ -322,32 +309,23 @@ public:
|
||||
struct BufferDefinition {
|
||||
u32 binding;
|
||||
BufferType buffer_type;
|
||||
Id offset;
|
||||
Id offset_dwords;
|
||||
Id size;
|
||||
Id size_shorts;
|
||||
Id size_dwords;
|
||||
Id size_qwords;
|
||||
std::array<Id, u32(PointerSize::NumClass)> offsets;
|
||||
std::array<Id, u32(PointerSize::NumClass)> sizes;
|
||||
std::array<BufferSpv, u32(PointerType::NumAlias)> aliases;
|
||||
|
||||
const BufferSpv& operator[](PointerType alias) const {
|
||||
return aliases[u32(alias)];
|
||||
template <class Self>
|
||||
auto& Alias(this Self& self, PointerType alias) {
|
||||
return self.aliases[u32(alias)];
|
||||
}
|
||||
|
||||
BufferSpv& operator[](PointerType alias) {
|
||||
return aliases[u32(alias)];
|
||||
}
|
||||
};
|
||||
|
||||
struct PhysicalPointerTypes {
|
||||
std::array<Id, u32(PointerType::NumAlias)> types;
|
||||
|
||||
const Id& operator[](PointerType type) const {
|
||||
return types[u32(type)];
|
||||
template <class Self>
|
||||
auto& Offset(this Self& self, PointerSize size) {
|
||||
return self.offsets[u32(size)];
|
||||
}
|
||||
|
||||
Id& operator[](PointerType type) {
|
||||
return types[u32(type)];
|
||||
template <class Self>
|
||||
auto& Size(this Self& self, PointerSize size) {
|
||||
return self.sizes[u32(size)];
|
||||
}
|
||||
};
|
||||
|
||||
@ -356,12 +334,12 @@ public:
|
||||
boost::container::small_vector<BufferDefinition, 16> buffers;
|
||||
boost::container::small_vector<TextureDefinition, 8> images;
|
||||
boost::container::small_vector<Id, 4> samplers;
|
||||
PhysicalPointerTypes physical_pointer_types;
|
||||
std::unordered_map<u32, Id> first_to_last_label_map;
|
||||
|
||||
size_t flatbuf_index{};
|
||||
size_t bda_pagetable_index{};
|
||||
size_t fault_buffer_index{};
|
||||
Id physical_pointer_type_u32;
|
||||
|
||||
Id sampler_type{};
|
||||
Id sampler_pointer_type{};
|
||||
|
@ -1,7 +1,6 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <bit>
|
||||
#include "common/assert.h"
|
||||
#include "shader_recompiler/frontend/translate/translate.h"
|
||||
|
||||
|
@ -58,6 +58,7 @@ struct BufferResource {
|
||||
BufferType buffer_type;
|
||||
u8 instance_attrib{};
|
||||
bool is_written{};
|
||||
bool is_read{};
|
||||
bool is_formatted{};
|
||||
|
||||
bool IsSpecial() const noexcept {
|
||||
@ -238,7 +239,7 @@ struct Info {
|
||||
Dynamic = 1 << 1,
|
||||
};
|
||||
ReadConstType readconst_types{};
|
||||
IR::Type dma_types{IR::Type::Void};
|
||||
bool uses_dma{false};
|
||||
|
||||
explicit Info(Stage stage_, LogicalStage l_stage_, ShaderParams params)
|
||||
: stage{stage_}, l_stage{l_stage_}, pgm_hash{params.hash}, pgm_base{params.Base()},
|
||||
|
@ -105,6 +105,49 @@ IR::Type BufferDataType(const IR::Inst& inst, AmdGpu::NumberFormat num_format) {
|
||||
}
|
||||
}
|
||||
|
||||
u32 BufferAddressShift(const IR::Inst& inst, AmdGpu::DataFormat data_format) {
|
||||
switch (inst.GetOpcode()) {
|
||||
case IR::Opcode::LoadBufferU8:
|
||||
case IR::Opcode::StoreBufferU8:
|
||||
return 0;
|
||||
case IR::Opcode::LoadBufferU16:
|
||||
case IR::Opcode::StoreBufferU16:
|
||||
return 1;
|
||||
case IR::Opcode::LoadBufferU64:
|
||||
case IR::Opcode::StoreBufferU64:
|
||||
case IR::Opcode::BufferAtomicIAdd64:
|
||||
return 3;
|
||||
case IR::Opcode::LoadBufferFormatF32:
|
||||
case IR::Opcode::StoreBufferFormatF32: {
|
||||
switch (data_format) {
|
||||
case AmdGpu::DataFormat::Format8:
|
||||
return 0;
|
||||
case AmdGpu::DataFormat::Format8_8:
|
||||
case AmdGpu::DataFormat::Format16:
|
||||
return 1;
|
||||
case AmdGpu::DataFormat::Format8_8_8_8:
|
||||
case AmdGpu::DataFormat::Format16_16:
|
||||
case AmdGpu::DataFormat::Format10_11_11:
|
||||
case AmdGpu::DataFormat::Format2_10_10_10:
|
||||
case AmdGpu::DataFormat::Format16_16_16_16:
|
||||
case AmdGpu::DataFormat::Format32:
|
||||
case AmdGpu::DataFormat::Format32_32:
|
||||
case AmdGpu::DataFormat::Format32_32_32:
|
||||
case AmdGpu::DataFormat::Format32_32_32_32:
|
||||
return 2;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IR::Opcode::ReadConstBuffer:
|
||||
// Provided address is already in dwords
|
||||
return 0;
|
||||
default:
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsImageAtomicInstruction(const IR::Inst& inst) {
|
||||
switch (inst.GetOpcode()) {
|
||||
case IR::Opcode::ImageAtomicIAdd32:
|
||||
@ -154,6 +197,7 @@ public:
|
||||
auto& buffer = buffer_resources[index];
|
||||
buffer.used_types |= desc.used_types;
|
||||
buffer.is_written |= desc.is_written;
|
||||
buffer.is_read |= desc.is_read;
|
||||
buffer.is_formatted |= desc.is_formatted;
|
||||
return index;
|
||||
}
|
||||
@ -324,6 +368,7 @@ s32 TryHandleInlineCbuf(IR::Inst& inst, Info& info, Descriptors& descriptors,
|
||||
.used_types = BufferDataType(inst, cbuf.GetNumberFmt()),
|
||||
.inline_cbuf = cbuf,
|
||||
.buffer_type = BufferType::Guest,
|
||||
.is_read = true,
|
||||
});
|
||||
}
|
||||
|
||||
@ -335,11 +380,13 @@ void PatchBufferSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
|
||||
IR::Inst* producer = handle->Arg(0).InstRecursive();
|
||||
SharpLocation sharp;
|
||||
std::tie(sharp, buffer) = TrackSharp<AmdGpu::Buffer>(producer, info);
|
||||
const bool is_written = IsBufferStore(inst);
|
||||
binding = descriptors.Add(BufferResource{
|
||||
.sharp_idx = sharp,
|
||||
.used_types = BufferDataType(inst, buffer.GetNumberFmt()),
|
||||
.buffer_type = BufferType::Guest,
|
||||
.is_written = IsBufferStore(inst),
|
||||
.is_written = is_written,
|
||||
.is_read = !is_written,
|
||||
.is_formatted = inst.GetOpcode() == IR::Opcode::LoadBufferFormatF32 ||
|
||||
inst.GetOpcode() == IR::Opcode::StoreBufferFormatF32,
|
||||
});
|
||||
@ -366,11 +413,12 @@ void PatchImageSharp(IR::Block& block, IR::Inst& inst, Info& info, Descriptors&
|
||||
// Read image sharp.
|
||||
const auto tsharp = TrackSharp(tsharp_handle, info);
|
||||
const auto inst_info = inst.Flags<IR::TextureInstInfo>();
|
||||
const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite;
|
||||
const bool is_atomic = IsImageAtomicInstruction(inst);
|
||||
const bool is_written = inst.GetOpcode() == IR::Opcode::ImageWrite || is_atomic;
|
||||
const ImageResource image_res = {
|
||||
.sharp_idx = tsharp,
|
||||
.is_depth = bool(inst_info.is_depth),
|
||||
.is_atomic = IsImageAtomicInstruction(inst),
|
||||
.is_atomic = is_atomic,
|
||||
.is_array = bool(inst_info.is_array),
|
||||
.is_written = is_written,
|
||||
.is_r128 = bool(inst_info.is_r128),
|
||||
@ -496,6 +544,22 @@ void PatchDataRingAccess(IR::Block& block, IR::Inst& inst, Info& info, Descripto
|
||||
IR::U32 CalculateBufferAddress(IR::IREmitter& ir, const IR::Inst& inst, const Info& info,
|
||||
const AmdGpu::Buffer& buffer, u32 stride) {
|
||||
const auto inst_info = inst.Flags<IR::BufferInstInfo>();
|
||||
const u32 inst_offset = inst_info.inst_offset.Value();
|
||||
const auto is_inst_typed = inst_info.inst_data_fmt != AmdGpu::DataFormat::FormatInvalid;
|
||||
const auto data_format = is_inst_typed
|
||||
? AmdGpu::RemapDataFormat(inst_info.inst_data_fmt.Value())
|
||||
: buffer.GetDataFmt();
|
||||
const u32 shift = BufferAddressShift(inst, data_format);
|
||||
const u32 mask = (1 << shift) - 1;
|
||||
|
||||
// If address calculation is of the form "index * const_stride + offset" with offset constant
|
||||
// and both const_stride and offset are divisible with the element size, apply shift directly.
|
||||
if (inst_info.index_enable && !inst_info.offset_enable && !buffer.swizzle_enable &&
|
||||
!buffer.add_tid_enable && (stride & mask) == 0 && (inst_offset & mask) == 0) {
|
||||
// buffer_offset = index * (const_stride >> shift) + (inst_offset >> shift)
|
||||
const IR::U32 index = IR::U32{inst.Arg(1)};
|
||||
return ir.IAdd(ir.IMul(index, ir.Imm32(stride >> shift)), ir.Imm32(inst_offset >> shift));
|
||||
}
|
||||
|
||||
// index = (inst_idxen ? vgpr_index : 0) + (const_add_tid_enable ? thread_id[5:0] : 0)
|
||||
IR::U32 index = ir.Imm32(0U);
|
||||
@ -512,7 +576,7 @@ IR::U32 CalculateBufferAddress(IR::IREmitter& ir, const IR::Inst& inst, const In
|
||||
index = ir.IAdd(index, thread_id);
|
||||
}
|
||||
// offset = (inst_offen ? vgpr_offset : 0) + inst_offset
|
||||
IR::U32 offset = ir.Imm32(inst_info.inst_offset.Value());
|
||||
IR::U32 offset = ir.Imm32(inst_offset);
|
||||
if (inst_info.offset_enable) {
|
||||
const IR::U32 vgpr_offset = inst_info.index_enable
|
||||
? IR::U32{ir.CompositeExtract(inst.Arg(1), 1)}
|
||||
@ -545,6 +609,9 @@ IR::U32 CalculateBufferAddress(IR::IREmitter& ir, const IR::Inst& inst, const In
|
||||
// buffer_offset = index * const_stride + offset
|
||||
buffer_offset = ir.IAdd(ir.IMul(index, const_stride), offset);
|
||||
}
|
||||
if (shift != 0) {
|
||||
buffer_offset = ir.ShiftRightLogical(buffer_offset, ir.Imm32(shift));
|
||||
}
|
||||
return buffer_offset;
|
||||
}
|
||||
|
||||
|
@ -102,7 +102,7 @@ void Visit(Info& info, const IR::Inst& inst) {
|
||||
info.uses_lane_id = true;
|
||||
break;
|
||||
case IR::Opcode::ReadConst:
|
||||
if (info.readconst_types == Info::ReadConstType::None) {
|
||||
if (!info.uses_dma) {
|
||||
info.buffers.push_back({
|
||||
.used_types = IR::Type::U32,
|
||||
// We can't guarantee that flatbuf will not grow past UBO
|
||||
@ -116,7 +116,7 @@ void Visit(Info& info, const IR::Inst& inst) {
|
||||
} else {
|
||||
info.readconst_types |= Info::ReadConstType::Dynamic;
|
||||
}
|
||||
info.dma_types |= IR::Type::U32;
|
||||
info.uses_dma = true;
|
||||
break;
|
||||
case IR::Opcode::PackUfloat10_11_11:
|
||||
info.uses_pack_10_11_11 = true;
|
||||
@ -130,21 +130,22 @@ void Visit(Info& info, const IR::Inst& inst) {
|
||||
}
|
||||
|
||||
void CollectShaderInfoPass(IR::Program& program) {
|
||||
auto& info = program.info;
|
||||
for (IR::Block* const block : program.post_order_blocks) {
|
||||
for (IR::Inst& inst : block->Instructions()) {
|
||||
Visit(program.info, inst);
|
||||
Visit(info, inst);
|
||||
}
|
||||
}
|
||||
|
||||
if (program.info.dma_types != IR::Type::Void) {
|
||||
program.info.buffers.push_back({
|
||||
if (info.uses_dma) {
|
||||
info.buffers.push_back({
|
||||
.used_types = IR::Type::U64,
|
||||
.inline_cbuf = AmdGpu::Buffer::Placeholder(VideoCore::BufferCache::BDA_PAGETABLE_SIZE),
|
||||
.buffer_type = BufferType::BdaPagetable,
|
||||
.is_written = true,
|
||||
});
|
||||
program.info.buffers.push_back({
|
||||
.used_types = IR::Type::U8,
|
||||
info.buffers.push_back({
|
||||
.used_types = IR::Type::U32,
|
||||
.inline_cbuf = AmdGpu::Buffer::Placeholder(VideoCore::BufferCache::FAULT_BUFFER_SIZE),
|
||||
.buffer_type = BufferType::FaultBuffer,
|
||||
.is_written = true,
|
||||
|
@ -35,7 +35,7 @@ struct Profile {
|
||||
bool lower_left_origin_mode{};
|
||||
bool needs_manual_interpolation{};
|
||||
bool needs_lds_barriers{};
|
||||
u64 min_ssbo_alignment{};
|
||||
bool needs_buffer_offsets{};
|
||||
u64 max_ubo_size{};
|
||||
u32 max_viewport_width{};
|
||||
u32 max_viewport_height{};
|
||||
|
@ -16,7 +16,7 @@ namespace VideoCore {
|
||||
class MemoryTracker {
|
||||
public:
|
||||
static constexpr size_t MAX_CPU_PAGE_BITS = 40;
|
||||
static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - HIGHER_PAGE_BITS);
|
||||
static constexpr size_t NUM_HIGH_PAGES = 1ULL << (MAX_CPU_PAGE_BITS - TRACKER_HIGHER_PAGE_BITS);
|
||||
static constexpr size_t MANAGER_POOL_SIZE = 32;
|
||||
|
||||
public:
|
||||
@ -90,11 +90,11 @@ private:
|
||||
using FuncReturn = typename std::invoke_result<Func, RegionManager*, u64, size_t>::type;
|
||||
static constexpr bool BOOL_BREAK = std::is_same_v<FuncReturn, bool>;
|
||||
std::size_t remaining_size{size};
|
||||
std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS};
|
||||
u64 page_offset{cpu_address & HIGHER_PAGE_MASK};
|
||||
std::size_t page_index{cpu_address >> TRACKER_HIGHER_PAGE_BITS};
|
||||
u64 page_offset{cpu_address & TRACKER_HIGHER_PAGE_MASK};
|
||||
while (remaining_size > 0) {
|
||||
const std::size_t copy_amount{
|
||||
std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)};
|
||||
std::min<std::size_t>(TRACKER_HIGHER_PAGE_SIZE - page_offset, remaining_size)};
|
||||
auto* manager{top_tier[page_index]};
|
||||
if (manager) {
|
||||
if constexpr (BOOL_BREAK) {
|
||||
@ -123,7 +123,7 @@ private:
|
||||
}
|
||||
|
||||
void CreateRegion(std::size_t page_index) {
|
||||
const VAddr base_cpu_addr = page_index << HIGHER_PAGE_BITS;
|
||||
const VAddr base_cpu_addr = page_index << TRACKER_HIGHER_PAGE_BITS;
|
||||
if (free_managers.empty()) {
|
||||
manager_pool.emplace_back();
|
||||
auto& last_pool = manager_pool.back();
|
||||
|
@ -9,13 +9,13 @@
|
||||
|
||||
namespace VideoCore {
|
||||
|
||||
constexpr u64 PAGES_PER_WORD = 64;
|
||||
constexpr u64 BYTES_PER_PAGE = 4_KB;
|
||||
constexpr u64 TRACKER_PAGE_BITS = 12; // 4K pages
|
||||
constexpr u64 TRACKER_BYTES_PER_PAGE = 1ULL << TRACKER_PAGE_BITS;
|
||||
|
||||
constexpr u64 HIGHER_PAGE_BITS = 22;
|
||||
constexpr u64 HIGHER_PAGE_SIZE = 1ULL << HIGHER_PAGE_BITS;
|
||||
constexpr u64 HIGHER_PAGE_MASK = HIGHER_PAGE_SIZE - 1ULL;
|
||||
constexpr u64 NUM_REGION_PAGES = HIGHER_PAGE_SIZE / BYTES_PER_PAGE;
|
||||
constexpr u64 TRACKER_HIGHER_PAGE_BITS = 24; // each region is 16MB
|
||||
constexpr u64 TRACKER_HIGHER_PAGE_SIZE = 1ULL << TRACKER_HIGHER_PAGE_BITS;
|
||||
constexpr u64 TRACKER_HIGHER_PAGE_MASK = TRACKER_HIGHER_PAGE_SIZE - 1ULL;
|
||||
constexpr u64 NUM_PAGES_PER_REGION = TRACKER_HIGHER_PAGE_SIZE / TRACKER_BYTES_PER_PAGE;
|
||||
|
||||
enum class Type {
|
||||
CPU,
|
||||
@ -23,6 +23,6 @@ enum class Type {
|
||||
Writeable,
|
||||
};
|
||||
|
||||
using RegionBits = Common::BitArray<NUM_REGION_PAGES>;
|
||||
using RegionBits = Common::BitArray<NUM_PAGES_PER_REGION>;
|
||||
|
||||
} // namespace VideoCore
|
@ -83,9 +83,10 @@ public:
|
||||
void ChangeRegionState(u64 dirty_addr, u64 size) noexcept(type == Type::GPU) {
|
||||
RENDERER_TRACE;
|
||||
const size_t offset = dirty_addr - cpu_addr;
|
||||
const size_t start_page = SanitizeAddress(offset) / BYTES_PER_PAGE;
|
||||
const size_t end_page = Common::DivCeil(SanitizeAddress(offset + size), BYTES_PER_PAGE);
|
||||
if (start_page >= NUM_REGION_PAGES || end_page <= start_page) {
|
||||
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
|
||||
const size_t end_page =
|
||||
Common::DivCeil(SanitizeAddress(offset + size), TRACKER_BYTES_PER_PAGE);
|
||||
if (start_page >= NUM_PAGES_PER_REGION || end_page <= start_page) {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lk{lock};
|
||||
@ -114,9 +115,10 @@ public:
|
||||
void ForEachModifiedRange(VAddr query_cpu_range, s64 size, auto&& func) {
|
||||
RENDERER_TRACE;
|
||||
const size_t offset = query_cpu_range - cpu_addr;
|
||||
const size_t start_page = SanitizeAddress(offset) / BYTES_PER_PAGE;
|
||||
const size_t end_page = Common::DivCeil(SanitizeAddress(offset + size), BYTES_PER_PAGE);
|
||||
if (start_page >= NUM_REGION_PAGES || end_page <= start_page) {
|
||||
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
|
||||
const size_t end_page =
|
||||
Common::DivCeil(SanitizeAddress(offset + size), TRACKER_BYTES_PER_PAGE);
|
||||
if (start_page >= NUM_PAGES_PER_REGION || end_page <= start_page) {
|
||||
return;
|
||||
}
|
||||
std::scoped_lock lk{lock};
|
||||
@ -131,7 +133,7 @@ public:
|
||||
}
|
||||
|
||||
for (const auto& [start, end] : mask) {
|
||||
func(cpu_addr + start * BYTES_PER_PAGE, (end - start) * BYTES_PER_PAGE);
|
||||
func(cpu_addr + start * TRACKER_BYTES_PER_PAGE, (end - start) * TRACKER_BYTES_PER_PAGE);
|
||||
}
|
||||
|
||||
if constexpr (clear) {
|
||||
@ -151,9 +153,10 @@ public:
|
||||
template <Type type>
|
||||
[[nodiscard]] bool IsRegionModified(u64 offset, u64 size) const noexcept {
|
||||
RENDERER_TRACE;
|
||||
const size_t start_page = SanitizeAddress(offset) / BYTES_PER_PAGE;
|
||||
const size_t end_page = Common::DivCeil(SanitizeAddress(offset + size), BYTES_PER_PAGE);
|
||||
if (start_page >= NUM_REGION_PAGES || end_page <= start_page) {
|
||||
const size_t start_page = SanitizeAddress(offset) / TRACKER_BYTES_PER_PAGE;
|
||||
const size_t end_page =
|
||||
Common::DivCeil(SanitizeAddress(offset + size), TRACKER_BYTES_PER_PAGE);
|
||||
if (start_page >= NUM_PAGES_PER_REGION || end_page <= start_page) {
|
||||
return false;
|
||||
}
|
||||
// std::scoped_lock lk{lock}; // Is this needed?
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include <boost/container/small_vector.hpp>
|
||||
#include "common/assert.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/range_lock.h"
|
||||
#include "common/signal_context.h"
|
||||
#include "core/memory.h"
|
||||
#include "core/signals.h"
|
||||
@ -59,6 +60,7 @@ struct PageManager::Impl {
|
||||
|
||||
static constexpr size_t ADDRESS_BITS = 40;
|
||||
static constexpr size_t NUM_ADDRESS_PAGES = 1ULL << (40 - PAGE_BITS);
|
||||
static constexpr size_t NUM_ADDRESS_LOCKS = NUM_ADDRESS_PAGES / PAGES_PER_LOCK;
|
||||
inline static Vulkan::Rasterizer* rasterizer;
|
||||
#ifdef ENABLE_USERFAULTFD
|
||||
Impl(Vulkan::Rasterizer* rasterizer_) {
|
||||
@ -191,9 +193,17 @@ struct PageManager::Impl {
|
||||
RENDERER_TRACE;
|
||||
|
||||
size_t page = addr >> PAGE_BITS;
|
||||
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
||||
|
||||
// Acquire locks for the range of pages
|
||||
const auto lock_start = locks.begin() + (page / PAGES_PER_LOCK);
|
||||
const auto lock_end = locks.begin() + Common::DivCeil(page_end, PAGES_PER_LOCK);
|
||||
Common::RangeLockGuard lk(lock_start, lock_end);
|
||||
|
||||
auto perms = cached_pages[page].Perm();
|
||||
u64 range_begin = 0;
|
||||
u64 range_bytes = 0;
|
||||
u64 potential_range_bytes = 0;
|
||||
|
||||
const auto release_pending = [&] {
|
||||
if (range_bytes > 0) {
|
||||
@ -201,13 +211,11 @@ struct PageManager::Impl {
|
||||
// Perform pending (un)protect action
|
||||
Protect(range_begin << PAGE_BITS, range_bytes, perms);
|
||||
range_bytes = 0;
|
||||
potential_range_bytes = 0;
|
||||
}
|
||||
};
|
||||
|
||||
std::scoped_lock lk(lock);
|
||||
|
||||
// Iterate requested pages
|
||||
const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE);
|
||||
const u64 aligned_addr = page << PAGE_BITS;
|
||||
const u64 aligned_end = page_end << PAGE_BITS;
|
||||
ASSERT_MSG(rasterizer->IsMapped(aligned_addr, aligned_end - aligned_addr),
|
||||
@ -225,14 +233,19 @@ struct PageManager::Impl {
|
||||
release_pending();
|
||||
perms = new_perms;
|
||||
} else if (range_bytes != 0) {
|
||||
// If the protection did not change, extend the current range
|
||||
range_bytes += PAGE_SIZE;
|
||||
// If the protection did not change, extend the potential range
|
||||
potential_range_bytes += PAGE_SIZE;
|
||||
}
|
||||
|
||||
// Only start a new range if the page must be (un)protected
|
||||
if (range_bytes == 0 && ((new_count == 0 && !track) || (new_count == 1 && track))) {
|
||||
range_begin = page;
|
||||
range_bytes = PAGE_SIZE;
|
||||
if ((new_count == 0 && !track) || (new_count == 1 && track)) {
|
||||
if (range_bytes == 0) {
|
||||
// Start a new potential range
|
||||
range_begin = page;
|
||||
potential_range_bytes = PAGE_SIZE;
|
||||
}
|
||||
// Extend current range up to potential range
|
||||
range_bytes = potential_range_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -256,9 +269,12 @@ struct PageManager::Impl {
|
||||
}
|
||||
|
||||
size_t base_page = (base_addr >> PAGE_BITS);
|
||||
ASSERT(base_page % PAGES_PER_LOCK == 0);
|
||||
std::scoped_lock lk(locks[base_page / PAGES_PER_LOCK]);
|
||||
auto perms = cached_pages[base_page + start_range.first].Perm();
|
||||
u64 range_begin = 0;
|
||||
u64 range_bytes = 0;
|
||||
u64 potential_range_bytes = 0;
|
||||
|
||||
const auto release_pending = [&] {
|
||||
if (range_bytes > 0) {
|
||||
@ -266,11 +282,10 @@ struct PageManager::Impl {
|
||||
// Perform pending (un)protect action
|
||||
Protect((range_begin << PAGE_BITS), range_bytes, perms);
|
||||
range_bytes = 0;
|
||||
potential_range_bytes = 0;
|
||||
}
|
||||
};
|
||||
|
||||
std::scoped_lock lk(lock);
|
||||
|
||||
// Iterate pages
|
||||
for (size_t page = start_range.first; page < end_range.second; ++page) {
|
||||
PageState& state = cached_pages[base_page + page];
|
||||
@ -284,8 +299,8 @@ struct PageManager::Impl {
|
||||
release_pending();
|
||||
perms = new_perms;
|
||||
} else if (range_bytes != 0) {
|
||||
// If the protection did not change, extend the current range
|
||||
range_bytes += PAGE_SIZE;
|
||||
// If the protection did not change, extend the potential range
|
||||
potential_range_bytes += PAGE_SIZE;
|
||||
}
|
||||
|
||||
// If the page is not being updated, skip it
|
||||
@ -293,10 +308,15 @@ struct PageManager::Impl {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only start a new range if the page must be (un)protected
|
||||
if (range_bytes == 0 && ((new_count == 0 && !track) || (new_count == 1 && track))) {
|
||||
range_begin = base_page + page;
|
||||
range_bytes = PAGE_SIZE;
|
||||
// If the page must be (un)protected
|
||||
if ((new_count == 0 && !track) || (new_count == 1 && track)) {
|
||||
if (range_bytes == 0) {
|
||||
// Start a new potential range
|
||||
range_begin = base_page + page;
|
||||
potential_range_bytes = PAGE_SIZE;
|
||||
}
|
||||
// Extend current rango up to potential range
|
||||
range_bytes = potential_range_bytes;
|
||||
}
|
||||
}
|
||||
|
||||
@ -306,10 +326,11 @@ struct PageManager::Impl {
|
||||
|
||||
std::array<PageState, NUM_ADDRESS_PAGES> cached_pages{};
|
||||
#ifdef __linux__
|
||||
Common::AdaptiveMutex lock;
|
||||
using LockType = Common::AdaptiveMutex;
|
||||
#else
|
||||
Common::SpinLock lock;
|
||||
using LockType = Common::SpinLock;
|
||||
#endif
|
||||
std::array<LockType, NUM_ADDRESS_LOCKS> locks{};
|
||||
};
|
||||
|
||||
PageManager::PageManager(Vulkan::Rasterizer* rasterizer_)
|
||||
|
@ -15,8 +15,13 @@ class Rasterizer;
|
||||
namespace VideoCore {
|
||||
|
||||
class PageManager {
|
||||
static constexpr size_t PAGE_BITS = 12;
|
||||
static constexpr size_t PAGE_SIZE = 1ULL << PAGE_BITS;
|
||||
// Use the same page size as the tracker.
|
||||
static constexpr size_t PAGE_BITS = TRACKER_PAGE_BITS;
|
||||
static constexpr size_t PAGE_SIZE = TRACKER_BYTES_PER_PAGE;
|
||||
|
||||
// Keep the lock granularity the same as region granularity. (since each regions has
|
||||
// itself a lock)
|
||||
static constexpr size_t PAGES_PER_LOCK = NUM_PAGES_PER_REGION;
|
||||
|
||||
public:
|
||||
explicit PageManager(Vulkan::Rasterizer* rasterizer);
|
||||
|
@ -225,6 +225,7 @@ PipelineCache::PipelineCache(const Instance& instance_, Scheduler& scheduler_,
|
||||
instance.GetDriverID() == vk::DriverId::eNvidiaProprietary,
|
||||
.needs_lds_barriers = instance.GetDriverID() == vk::DriverId::eNvidiaProprietary ||
|
||||
instance.GetDriverID() == vk::DriverId::eMoltenvk,
|
||||
.needs_buffer_offsets = instance.StorageMinAlignment() > 4,
|
||||
// When binding a UBO, we calculate its size considering the offset in the larger buffer
|
||||
// cache underlying resource. In some cases, it may produce sizes exceeding the system
|
||||
// maximum allowed UBO range, so we need to reduce the threshold to prevent issues.
|
||||
|
@ -468,17 +468,12 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
|
||||
stage->PushUd(binding, push_data);
|
||||
BindBuffers(*stage, binding, push_data);
|
||||
BindTextures(*stage, binding);
|
||||
|
||||
uses_dma |= stage->dma_types != Shader::IR::Type::Void;
|
||||
uses_dma |= stage->uses_dma;
|
||||
}
|
||||
|
||||
pipeline->BindResources(set_writes, buffer_barriers, push_data);
|
||||
|
||||
if (uses_dma && !fault_process_pending) {
|
||||
// We only use fault buffer for DMA right now.
|
||||
{
|
||||
// TODO: GPU might have written to memory (for example with EVENT_WRITE_EOP)
|
||||
// we need to account for that and synchronize.
|
||||
Common::RecursiveSharedLock lock{mapped_ranges_mutex};
|
||||
for (auto& range : mapped_ranges) {
|
||||
buffer_cache.SynchronizeBuffersInRange(range.lower(),
|
||||
@ -490,6 +485,8 @@ bool Rasterizer::BindResources(const Pipeline* pipeline) {
|
||||
|
||||
fault_process_pending |= uses_dma;
|
||||
|
||||
pipeline->BindResources(set_writes, buffer_barriers, push_data);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -514,7 +511,8 @@ bool Rasterizer::IsComputeMetaClear(const Pipeline* pipeline) {
|
||||
// will need its full emulation anyways.
|
||||
for (const auto& desc : info.buffers) {
|
||||
const VAddr address = desc.GetSharp(info).base_address;
|
||||
if (!desc.IsSpecial() && desc.is_written && texture_cache.ClearMeta(address)) {
|
||||
if (!desc.IsSpecial() && desc.is_written && !desc.is_read &&
|
||||
texture_cache.ClearMeta(address)) {
|
||||
// Assume all slices were updates
|
||||
LOG_TRACE(Render_Vulkan, "Metadata update skipped");
|
||||
return true;
|
||||
|
@ -27,10 +27,9 @@ enum ImageFlagBits : u32 {
|
||||
CpuDirty = 1 << 1, ///< Contents have been modified from the CPU
|
||||
GpuDirty = 1 << 2, ///< Contents have been modified from the GPU (valid data in buffer cache)
|
||||
Dirty = MaybeCpuDirty | CpuDirty | GpuDirty,
|
||||
GpuModified = 1 << 3, ///< Contents have been modified from the GPU
|
||||
Registered = 1 << 6, ///< True when the image is registered
|
||||
Picked = 1 << 7, ///< Temporary flag to mark the image as picked
|
||||
MetaRegistered = 1 << 8, ///< True when metadata for this surface is known and registered
|
||||
GpuModified = 1 << 3, ///< Contents have been modified from the GPU
|
||||
Registered = 1 << 6, ///< True when the image is registered
|
||||
Picked = 1 << 7, ///< Temporary flag to mark the image as picked
|
||||
};
|
||||
DECLARE_ENUM_FLAG_OPERATORS(ImageFlagBits)
|
||||
|
||||
|
@ -451,20 +451,16 @@ ImageView& TextureCache::FindRenderTarget(BaseDesc& desc) {
|
||||
UpdateImage(image_id);
|
||||
|
||||
// Register meta data for this color buffer
|
||||
if (!(image.flags & ImageFlagBits::MetaRegistered)) {
|
||||
if (desc.info.meta_info.cmask_addr) {
|
||||
surface_metas.emplace(desc.info.meta_info.cmask_addr,
|
||||
MetaDataInfo{.type = MetaDataInfo::Type::CMask});
|
||||
image.info.meta_info.cmask_addr = desc.info.meta_info.cmask_addr;
|
||||
image.flags |= ImageFlagBits::MetaRegistered;
|
||||
}
|
||||
if (desc.info.meta_info.cmask_addr) {
|
||||
surface_metas.emplace(desc.info.meta_info.cmask_addr,
|
||||
MetaDataInfo{.type = MetaDataInfo::Type::CMask});
|
||||
image.info.meta_info.cmask_addr = desc.info.meta_info.cmask_addr;
|
||||
}
|
||||
|
||||
if (desc.info.meta_info.fmask_addr) {
|
||||
surface_metas.emplace(desc.info.meta_info.fmask_addr,
|
||||
MetaDataInfo{.type = MetaDataInfo::Type::FMask});
|
||||
image.info.meta_info.fmask_addr = desc.info.meta_info.fmask_addr;
|
||||
image.flags |= ImageFlagBits::MetaRegistered;
|
||||
}
|
||||
if (desc.info.meta_info.fmask_addr) {
|
||||
surface_metas.emplace(desc.info.meta_info.fmask_addr,
|
||||
MetaDataInfo{.type = MetaDataInfo::Type::FMask});
|
||||
image.info.meta_info.fmask_addr = desc.info.meta_info.fmask_addr;
|
||||
}
|
||||
|
||||
return RegisterImageView(image_id, desc.view_info);
|
||||
@ -479,15 +475,11 @@ ImageView& TextureCache::FindDepthTarget(BaseDesc& desc) {
|
||||
UpdateImage(image_id);
|
||||
|
||||
// Register meta data for this depth buffer
|
||||
if (!(image.flags & ImageFlagBits::MetaRegistered)) {
|
||||
if (desc.info.meta_info.htile_addr) {
|
||||
surface_metas.emplace(
|
||||
desc.info.meta_info.htile_addr,
|
||||
MetaDataInfo{.type = MetaDataInfo::Type::HTile,
|
||||
.clear_mask = image.info.meta_info.htile_clear_mask});
|
||||
image.info.meta_info.htile_addr = desc.info.meta_info.htile_addr;
|
||||
image.flags |= ImageFlagBits::MetaRegistered;
|
||||
}
|
||||
if (desc.info.meta_info.htile_addr) {
|
||||
surface_metas.emplace(desc.info.meta_info.htile_addr,
|
||||
MetaDataInfo{.type = MetaDataInfo::Type::HTile,
|
||||
.clear_mask = image.info.meta_info.htile_clear_mask});
|
||||
image.info.meta_info.htile_addr = desc.info.meta_info.htile_addr;
|
||||
}
|
||||
|
||||
// If there is a stencil attachment, link depth and stencil.
|
||||
|
Loading…
Reference in New Issue
Block a user