mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-12-06 07:12:28 +01:00
Merge branch 'master' into nastys-patch-17
This commit is contained in:
commit
b53e8e17ac
|
|
@ -38,7 +38,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
||||||
git clone https://github.com/engnr/qt-downloader.git
|
git clone https://github.com/engnr/qt-downloader.git
|
||||||
cd qt-downloader
|
cd qt-downloader
|
||||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||||
# nested Qt 6.10.0 URL workaround
|
# nested Qt 6.10.1 URL workaround
|
||||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||||
# archived Qt 6.7.3 URL workaround
|
# archived Qt 6.7.3 URL workaround
|
||||||
|
|
@ -47,7 +47,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
||||||
"$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml
|
"$BREW_PATH/bin/pipenv" run pip3 uninstall py7zr requests semantic_version lxml
|
||||||
"$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache
|
"$BREW_PATH/bin/pipenv" run pip3 install py7zr requests semantic_version lxml --no-cache
|
||||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.0 workaround
|
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.1 workaround
|
||||||
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
"$BREW_PATH/bin/pipenv" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
||||||
git clone https://github.com/engnr/qt-downloader.git
|
git clone https://github.com/engnr/qt-downloader.git
|
||||||
cd qt-downloader
|
cd qt-downloader
|
||||||
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
git checkout f52efee0f18668c6d6de2dec0234b8c4bc54c597
|
||||||
# nested Qt 6.10.0 URL workaround
|
# nested Qt 6.10.1 URL workaround
|
||||||
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
# sed -i '' "s/'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/'qt{0}_{0}{1}{2}'.format(major, minor, patch), 'qt{0}_{0}{1}{2}'.format(major, minor, patch)]))/g" qt-downloader
|
||||||
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
# sed -i '' "s/'{}\/{}\/qt{}_{}\/'/'{0}\/{1}\/qt{2}_{3}\/qt{2}_{3}\/'/g" qt-downloader
|
||||||
# archived Qt 6.7.3 URL workaround
|
# archived Qt 6.7.3 URL workaround
|
||||||
|
|
@ -46,7 +46,7 @@ if [ ! -d "/tmp/Qt/$QT_VER" ]; then
|
||||||
cd "/tmp/Qt"
|
cd "/tmp/Qt"
|
||||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml
|
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run pip3 install py7zr requests semantic_version lxml
|
||||||
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
mkdir -p "$QT_VER/macos" ; ln -s "macos" "$QT_VER/clang_64"
|
||||||
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.0 workaround
|
# sed -i '' 's/args\.version \/ derive_toolchain_dir(args) \/ //g' "$WORKDIR/qt-downloader/qt-downloader" # Qt 6.10.1 workaround
|
||||||
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
"/opt/homebrew/bin/pipenv" --python "/opt/homebrew/bin/python3" run "$WORKDIR/qt-downloader/qt-downloader" macos desktop "$QT_VER" clang_64 --opensource --addons qtmultimedia qtimageformats # -o "$QT_VER/clang_64"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|
|
||||||
4
.github/workflows/rpcs3.yml
vendored
4
.github/workflows/rpcs3.yml
vendored
|
|
@ -212,9 +212,9 @@ jobs:
|
||||||
env:
|
env:
|
||||||
COMPILER: msvc
|
COMPILER: msvc
|
||||||
QT_VER_MAIN: '6'
|
QT_VER_MAIN: '6'
|
||||||
QT_VER: '6.10.0'
|
QT_VER: '6.10.1'
|
||||||
QT_VER_MSVC: 'msvc2022'
|
QT_VER_MSVC: 'msvc2022'
|
||||||
QT_DATE: '202510021201'
|
QT_DATE: '202511161843'
|
||||||
LLVM_VER: '19.1.7'
|
LLVM_VER: '19.1.7'
|
||||||
VULKAN_VER: '1.3.268.0'
|
VULKAN_VER: '1.3.268.0'
|
||||||
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
VULKAN_SDK_SHA: '8459ef49bd06b697115ddd3d97c9aec729e849cd775f5be70897718a9b3b9db5'
|
||||||
|
|
|
||||||
2
3rdparty/libpng/libpng
vendored
2
3rdparty/libpng/libpng
vendored
|
|
@ -1 +1 @@
|
||||||
Subproject commit 2b978915d82377df13fcbb1fb56660195ded868a
|
Subproject commit 49363adcfaf098748d7a4c8c624ad8c45a8c3a86
|
||||||
15
BUILDING.md
15
BUILDING.md
|
|
@ -8,37 +8,38 @@ Other instructions may be found [here](https://wiki.rpcs3.net/index.php?title=Bu
|
||||||
### Windows 10 or later
|
### Windows 10 or later
|
||||||
|
|
||||||
The following tools are required to build RPCS3 on Windows 10 or later:
|
The following tools are required to build RPCS3 on Windows 10 or later:
|
||||||
- [Visual Studio 2022](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
|
- [Visual Studio 2022/2026](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=Community)
|
||||||
- **Optional** - [CMake 3.28.0+](https://www.cmake.org/download/) (add to PATH)
|
- **Optional** - [CMake 3.28.0+](https://www.cmake.org/download/) (add to PATH)
|
||||||
|
|
||||||
**NOTES:**
|
**NOTES:**
|
||||||
- **Visual Studio 2022** integrates **CMake 3.29+** and it also supports both the `sln` solution (`.sln`, `.vcxproj`) and `CMake` solution (`CMakeLists.txt`, `CMakePresets.json`).
|
- **Visual Studio 2026** needs at least **CMake 4.2.0+**.
|
||||||
|
- **Visual Studio 2022/2026** integrates **CMake 3.29+** and it also supports both the `sln` solution (`.sln`, `.vcxproj`) and `CMake` solution (`CMakeLists.txt`, `CMakePresets.json`).
|
||||||
See sections [Building with Visual Studio sln solution](#building-with-visual-studio-sln-solution) and [Building with Visual Studio CMake solution](#building-with-visual-studio-cmake-solution)
|
See sections [Building with Visual Studio sln solution](#building-with-visual-studio-sln-solution) and [Building with Visual Studio CMake solution](#building-with-visual-studio-cmake-solution)
|
||||||
on how to build the project with **Visual Studio**.
|
on how to build the project with **Visual Studio**.
|
||||||
- Install and use this standalone **CMake** tool just in case of your preference. See section [Building with standalone CMake tool](#building-with-standalone-cmake-tool) on how to build the project
|
- Install and use this standalone **CMake** tool just in case of your preference. See section [Building with standalone CMake tool](#building-with-standalone-cmake-tool) on how to build the project
|
||||||
with standalone **CMake** tool.
|
with standalone **CMake** tool.
|
||||||
|
|
||||||
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
- [Python 3.6+](https://www.python.org/downloads/) (add to PATH)
|
||||||
- [Qt 6.10.0](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
|
- [Qt 6.10.1](https://www.qt.io/download-qt-installer) In case you can't download from the official installer, you can use [Another Qt installer](https://github.com/miurahr/aqtinstall) (In that case you will need to manually add the "qtmultimedia" module when installing Qt)
|
||||||
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (see "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/windows/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
||||||
|
|
||||||
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
|
The `sln` solution available only on **Visual Studio** is the preferred building solution. It easily allows to build the **RPCS3** application in `Release` and `Debug` mode.
|
||||||
|
|
||||||
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
|
In order to build **RPCS3** with the `sln` solution (with **Visual Studio**), **Qt** libs need to be detected. To detect the libs:
|
||||||
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.10.0\msvc2022_64\`
|
- add and set the `QTDIR` environment variable, e.g. `<QtInstallFolder>\6.10.1\msvc2022_64\`
|
||||||
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
|
- or use the [Visual Studio Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.QtVisualStudioTools2022)
|
||||||
|
|
||||||
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
|
**NOTE:** If you have issues with the **Visual Studio Qt Plugin**, you may want to uninstall it and install the [Legacy Qt Plugin](https://marketplace.visualstudio.com/items?itemName=TheQtCompany.LEGACYQtVisualStudioTools2022) instead.
|
||||||
|
|
||||||
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
|
In order to build **RPCS3** with the `CMake` solution (with both **Visual Studio** and standalone **CMake** tool):
|
||||||
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.10.0\msvc2022_64\`
|
- add and set the `Qt6_ROOT` environment variable to the **Qt** libs path, e.g. `<QtInstallFolder>\6.10.1\msvc2022_64\`
|
||||||
|
|
||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
|
These are the essentials tools to build RPCS3 on Linux. Some of them can be installed through your favorite package manager:
|
||||||
- Clang 17+ or GCC 13+
|
- Clang 17+ or GCC 13+
|
||||||
- [CMake 3.28.0+](https://www.cmake.org/download/)
|
- [CMake 3.28.0+](https://www.cmake.org/download/)
|
||||||
- [Qt 6.10.0](https://www.qt.io/download-qt-installer)
|
- [Qt 6.10.1](https://www.qt.io/download-qt-installer)
|
||||||
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
- [Vulkan SDK 1.3.268.0](https://vulkan.lunarg.com/sdk/home) (See "Install the SDK" [here](https://vulkan.lunarg.com/doc/sdk/latest/linux/getting_started.html)) for now future SDKs don't work. You need precisely 1.3.268.0.
|
||||||
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
|
- [SDL3](https://github.com/libsdl-org/SDL/releases) (for the FAudio backend)
|
||||||
|
|
||||||
|
|
@ -121,7 +122,7 @@ Start **Visual Studio**, click on `Open a project or solution` and select the `r
|
||||||
##### Configuring the Qt Plugin (if used)
|
##### Configuring the Qt Plugin (if used)
|
||||||
|
|
||||||
1) go to `Extensions->Qt VS Tools->Qt Versions`
|
1) go to `Extensions->Qt VS Tools->Qt Versions`
|
||||||
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.10.0\msvc2022_64`, version will fill in automatically
|
2) add the path to your Qt installation with compiler e.g. `<QtInstallFolder>\6.10.1\msvc2022_64`, version will fill in automatically
|
||||||
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
|
3) go to `Extensions->Qt VS Tools->Options->Legacy Project Format`. (Only available in the **Legacy Qt Plugin**)
|
||||||
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
|
4) set `Build: Run pre-build setup` to `true`. (Only available in the **Legacy Qt Plugin**)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -827,14 +827,14 @@ extern void ppu_register_function_at(u32 addr, u32 size, ppu_intrp_func_t ptr =
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size = utils::align<u32>(size + addr % 4, 4);
|
|
||||||
addr &= -4;
|
|
||||||
|
|
||||||
if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm)
|
if (g_cfg.core.ppu_decoder == ppu_decoder_type::llvm)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size = utils::align<u32>(size + addr % 4, 4);
|
||||||
|
addr &= -4;
|
||||||
|
|
||||||
// Initialize interpreter cache
|
// Initialize interpreter cache
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -720,9 +720,19 @@ void spu_cache::initialize(bool build_existing_cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SPU cache file (version + block size type)
|
// SPU cache file (version + block size type)
|
||||||
const std::string loc = ppu_cache + "spu-" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v1-tane.dat";
|
const std::string filename = "spu-" + fmt::to_lower(g_cfg.core.spu_block_size.to_string()) + "-v1-tane.dat";
|
||||||
|
const std::string loc = ppu_cache + filename;
|
||||||
|
const std::string loc_debug = fs::get_cache_dir() + "DEBUG/" + filename;
|
||||||
|
|
||||||
spu_cache cache(loc);
|
bool is_debug = false;
|
||||||
|
|
||||||
|
if (fs::is_file(loc_debug))
|
||||||
|
{
|
||||||
|
spu_log.success("SPU Cache override applied!");
|
||||||
|
is_debug = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
spu_cache cache(is_debug ? loc_debug : loc);
|
||||||
|
|
||||||
if (!cache)
|
if (!cache)
|
||||||
{
|
{
|
||||||
|
|
@ -4963,6 +4973,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
u32 lsa_last_pc = SPU_LS_SIZE; // PC of first LSA write
|
u32 lsa_last_pc = SPU_LS_SIZE; // PC of first LSA write
|
||||||
u32 get_pc = SPU_LS_SIZE; // PC of GETLLAR
|
u32 get_pc = SPU_LS_SIZE; // PC of GETLLAR
|
||||||
u32 put_pc = SPU_LS_SIZE; // PC of PUTLLC
|
u32 put_pc = SPU_LS_SIZE; // PC of PUTLLC
|
||||||
|
u32 rdatomic_pc = SPU_LS_SIZE; // PC of last RdAtomcStat read
|
||||||
reg_state_t ls{}; // state of LS load/store address register
|
reg_state_t ls{}; // state of LS load/store address register
|
||||||
reg_state_t ls_offs = reg_state_t::from_value(0); // Added value to ls
|
reg_state_t ls_offs = reg_state_t::from_value(0); // Added value to ls
|
||||||
reg_state_t lsa{}; // state of LSA register on GETLLAR
|
reg_state_t lsa{}; // state of LSA register on GETLLAR
|
||||||
|
|
@ -5008,7 +5019,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
ls_invalid = true;
|
ls_invalid = true;
|
||||||
ls_write |= write;
|
ls_write |= write;
|
||||||
|
|
||||||
if (write)
|
if (ls_write)
|
||||||
{
|
{
|
||||||
return discard();
|
return discard();
|
||||||
}
|
}
|
||||||
|
|
@ -6323,6 +6334,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
atomic16->rdatomic_pc = pos;
|
||||||
|
|
||||||
const auto it = atomic16_all.find(pos);
|
const auto it = atomic16_all.find(pos);
|
||||||
|
|
||||||
if (it == atomic16_all.end())
|
if (it == atomic16_all.end())
|
||||||
|
|
@ -7263,7 +7276,7 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
|
|
||||||
for (const auto& [pc_commited, pattern] : atomic16_all)
|
for (const auto& [pc_commited, pattern] : atomic16_all)
|
||||||
{
|
{
|
||||||
if (!pattern.active)
|
if (!pattern.active || pattern.lsa_pc >= pattern.rdatomic_pc)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -7273,6 +7286,17 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string pattern_hash;
|
||||||
|
{
|
||||||
|
sha1_context ctx;
|
||||||
|
u8 output[20]{};
|
||||||
|
|
||||||
|
sha1_starts(&ctx);
|
||||||
|
sha1_update(&ctx, reinterpret_cast<const u8*>(result.data.data()) + (pattern.lsa_pc - result.lower_bound), pattern.rdatomic_pc - pattern.lsa_pc);
|
||||||
|
sha1_finish(&ctx, output);
|
||||||
|
fmt::append(pattern_hash, "%s", fmt::base57(output));
|
||||||
|
}
|
||||||
|
|
||||||
union putllc16_or_0_info
|
union putllc16_or_0_info
|
||||||
{
|
{
|
||||||
u64 data;
|
u64 data;
|
||||||
|
|
@ -7295,8 +7319,8 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
value.required_pc = pattern.required_pc;
|
value.required_pc = pattern.required_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
spu_log.success("PUTLLC0 Pattern Detected! (put_pc=0x%x, %s) (putllc0=%d, putllc16+0=%d, all=%d)", pattern.put_pc, func_hash, ++stats.nowrite, ++stats.single, +stats.all);
|
// spu_log.success("PUTLLC0 Pattern Detected! (put_pc=0x%x, %s) (putllc0=%d, putllc16+0=%d, all=%d)", pattern.put_pc, func_hash, ++stats.nowrite, ++stats.single, +stats.all);
|
||||||
add_pattern(false, inst_attr::putllc0, pattern.put_pc - lsa, value.data);
|
// add_pattern(false, inst_attr::putllc0, pattern.put_pc - lsa, value.data);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -7363,16 +7387,35 @@ spu_program spu_recompiler_base::analyse(const be_t<u32>* ls, u32 entry_point, s
|
||||||
value.reg2 = pattern.reg2;
|
value.reg2 = pattern.reg2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool allow_pattern = true;
|
||||||
|
|
||||||
if (g_cfg.core.spu_accurate_reservations)
|
if (g_cfg.core.spu_accurate_reservations)
|
||||||
{
|
{
|
||||||
// Because enabling it is a hack, as it turns out
|
// The problem with PUTLLC16 optimization, that it is in theory correct at the bounds of the spu function.
|
||||||
// continue;
|
// But if the SPU code reuses the cache line data observed, it is not truly atomic.
|
||||||
|
// So we may enable it only for known cases where SPU atomic data is not used after the function leaves.
|
||||||
|
|
||||||
|
// So the two options are:
|
||||||
|
|
||||||
|
// 1. Atomic compare exchange 16 bytes operation. (rest of data is not read) -> good for RPCS3 to optimize.
|
||||||
|
// 2. Fetch 128 bytes (read them later), modify only 16 bytes. -> Bad for RPCS3 to optimize.
|
||||||
|
|
||||||
|
// This difference cannot be known at analyzer time but from observing callers.
|
||||||
|
static constexpr std::initializer_list<std::string_view> allowed_patterns =
|
||||||
|
{
|
||||||
|
"620oYSe8uQqq9eTkhWfMqoEXX0us"sv, // CellSpurs JobChain acquire pattern
|
||||||
|
};
|
||||||
|
|
||||||
|
allow_pattern = std::any_of(allowed_patterns.begin(), allowed_patterns.end(), FN(pattern_hash == x));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (allow_pattern)
|
||||||
|
{
|
||||||
add_pattern(false, inst_attr::putllc16, pattern.put_pc - result.entry_point, value.data);
|
add_pattern(false, inst_attr::putllc16, pattern.put_pc - result.entry_point, value.data);
|
||||||
|
}
|
||||||
|
|
||||||
spu_log.success("PUTLLC16 Pattern Detected! (mem_count=%d, put_pc=0x%x, pc_rel=%d, offset=0x%x, const=%u, two_regs=%d, reg=%u, runtime=%d, 0x%x-%s) (putllc0=%d, putllc16+0=%d, all=%d)"
|
spu_log.success("PUTLLC16 Pattern Detected! (mem_count=%d, put_pc=0x%x, pc_rel=%d, offset=0x%x, const=%u, two_regs=%d, reg=%u, runtime=%d, 0x%x-%s, pattern-hash=%s) (putllc0=%d, putllc16+0=%d, all=%d)"
|
||||||
, pattern.mem_count, pattern.put_pc, value.type == v_relative, value.off18, value.type == v_const, value.type == v_reg2, value.reg, value.runtime16_select, entry_point, func_hash, +stats.nowrite, ++stats.single, +stats.all);
|
, pattern.mem_count, pattern.put_pc, value.type == v_relative, value.off18, value.type == v_const, value.type == v_reg2, value.reg, value.runtime16_select, entry_point, func_hash, pattern_hash, +stats.nowrite, ++stats.single, +stats.all);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& [read_pc, pattern] : rchcnt_loop_all)
|
for (const auto& [read_pc, pattern] : rchcnt_loop_all)
|
||||||
|
|
@ -8435,8 +8478,9 @@ std::array<reg_state_t, s_reg_max>& block_reg_info::evaluate_start_state(const s
|
||||||
{
|
{
|
||||||
// TODO: The true maximum occurence count need to depend on the amount of branching-outs passed through
|
// TODO: The true maximum occurence count need to depend on the amount of branching-outs passed through
|
||||||
// Currently allow 2 for short-term code and 1 for long-term code
|
// Currently allow 2 for short-term code and 1 for long-term code
|
||||||
|
// Ignore large jumptables as well
|
||||||
const bool loop_terminator_detected = std::count(been_there.begin(), been_there.end(), prev_pc) >= (qi < 20 ? 2u : 1u);
|
const bool loop_terminator_detected = std::count(been_there.begin(), been_there.end(), prev_pc) >= (qi < 20 ? 2u : 1u);
|
||||||
const bool avoid_extensive_analysis = qi >= (extensive_evaluation ? 22 : 16);
|
const bool avoid_extensive_analysis = qi >= (extensive_evaluation ? 22 : 16) || it->state_prev.size() >= 8;
|
||||||
|
|
||||||
if (!loop_terminator_detected && !avoid_extensive_analysis)
|
if (!loop_terminator_detected && !avoid_extensive_analysis)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "../overlay_manager.h"
|
#include "../overlay_manager.h"
|
||||||
#include "overlay_friends_list_dialog.h"
|
#include "overlay_friends_list_dialog.h"
|
||||||
#include "Emu/System.h"
|
|
||||||
#include "Emu/NP/rpcn_config.h"
|
#include "Emu/NP/rpcn_config.h"
|
||||||
#include "Emu/vfs_config.h"
|
#include "Emu/vfs_config.h"
|
||||||
|
|
||||||
|
|
@ -306,11 +305,11 @@ namespace rsx
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::square:
|
case pad_button::square:
|
||||||
|
|
@ -359,7 +358,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlay_home_menu_message_box.h"
|
#include "overlay_home_menu_message_box.h"
|
||||||
#include "Emu/System.h"
|
|
||||||
#include "Emu/system_config.h"
|
#include "Emu/system_config.h"
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
|
|
@ -77,7 +76,7 @@ namespace rsx
|
||||||
{
|
{
|
||||||
case pad_button::cross:
|
case pad_button::cross:
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
if (m_on_accept)
|
if (m_on_accept)
|
||||||
{
|
{
|
||||||
m_on_accept();
|
m_on_accept();
|
||||||
|
|
@ -86,7 +85,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
if (m_on_cancel)
|
if (m_on_cancel)
|
||||||
{
|
{
|
||||||
m_on_cancel();
|
m_on_cancel();
|
||||||
|
|
|
||||||
|
|
@ -160,7 +160,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
if (!is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default)
|
if (!is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
}
|
}
|
||||||
return func(button_press);
|
return func(button_press);
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +169,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
if (parent)
|
if (parent)
|
||||||
{
|
{
|
||||||
set_current_page(parent);
|
set_current_page(parent);
|
||||||
|
|
@ -244,7 +244,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
if (!is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default)
|
if (!is_auto_repeat || auto_repeat_interval_ms >= user_interface::m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
return page_navigation::stay;
|
return page_navigation::stay;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,11 +127,11 @@ namespace rsx
|
||||||
{
|
{
|
||||||
return_code = selection_code::error;
|
return_code = selection_code::error;
|
||||||
}
|
}
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::dpad_up:
|
case pad_button::dpad_up:
|
||||||
|
|
@ -167,7 +167,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -82,7 +82,7 @@ namespace rsx
|
||||||
if (m_list->m_items.empty() || is_auto_repeat)
|
if (m_list->m_items.empty() || is_auto_repeat)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
|
|
||||||
if (!get_current_selection().empty())
|
if (!get_current_selection().empty())
|
||||||
{
|
{
|
||||||
|
|
@ -95,7 +95,7 @@ namespace rsx
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::dpad_up:
|
case pad_button::dpad_up:
|
||||||
|
|
@ -131,7 +131,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,7 +132,7 @@ namespace rsx
|
||||||
switch (button_press)
|
switch (button_press)
|
||||||
{
|
{
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::square:
|
case pad_button::square:
|
||||||
|
|
@ -172,7 +172,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
#include "overlay_media_list_dialog.h"
|
#include "overlay_media_list_dialog.h"
|
||||||
|
|
||||||
#include "Emu/Cell/Modules/cellMusic.h"
|
#include "Emu/Cell/Modules/cellMusic.h"
|
||||||
#include "Emu/System.h"
|
|
||||||
#include "Emu/VFS.h"
|
#include "Emu/VFS.h"
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
#include "Utilities/Thread.h"
|
#include "Utilities/Thread.h"
|
||||||
|
|
@ -154,13 +153,13 @@ namespace rsx
|
||||||
return_code = m_list->get_selected_index();
|
return_code = m_list->get_selected_index();
|
||||||
m_stop_input_loop = true;
|
m_stop_input_loop = true;
|
||||||
play_cursor_sound = false;
|
play_cursor_sound = false;
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
break;
|
break;
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
return_code = selection_code::canceled;
|
return_code = selection_code::canceled;
|
||||||
m_stop_input_loop = true;
|
m_stop_input_loop = true;
|
||||||
play_cursor_sound = false;
|
play_cursor_sound = false;
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
break;
|
break;
|
||||||
case pad_button::dpad_up:
|
case pad_button::dpad_up:
|
||||||
m_list->select_previous();
|
m_list->select_previous();
|
||||||
|
|
@ -182,7 +181,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
if (play_cursor_sound && (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default))
|
if (play_cursor_sound && (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default))
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -155,7 +155,7 @@ namespace rsx
|
||||||
return_code = CELL_MSGDIALOG_BUTTON_YES;
|
return_code = CELL_MSGDIALOG_BUTTON_YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
|
|
@ -175,7 +175,7 @@ namespace rsx
|
||||||
return_code = CELL_MSGDIALOG_BUTTON_NO;
|
return_code = CELL_MSGDIALOG_BUTTON_NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: return;
|
default: return;
|
||||||
|
|
@ -238,10 +238,7 @@ namespace rsx
|
||||||
|
|
||||||
if (!type.se_mute_on)
|
if (!type.se_mute_on)
|
||||||
{
|
{
|
||||||
if (type.se_normal)
|
play_sound(type.se_normal ? sound_effect::dialog_ok : sound_effect::dialog_error);
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_system_ok.wav");
|
|
||||||
else
|
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_system_ng.wav");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_text(text);
|
set_text(text);
|
||||||
|
|
|
||||||
|
|
@ -823,7 +823,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
case pad_button::start:
|
case pad_button::start:
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_oskenter.wav");
|
play_sound(sound_effect::osk_accept);
|
||||||
Close(CELL_OSKDIALOG_CLOSE_CONFIRM);
|
Close(CELL_OSKDIALOG_CLOSE_CONFIRM);
|
||||||
play_cursor_sound = false;
|
play_cursor_sound = false;
|
||||||
break;
|
break;
|
||||||
|
|
@ -840,7 +840,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
case pad_button::cross:
|
case pad_button::cross:
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_oskenter.wav");
|
play_sound(sound_effect::osk_accept);
|
||||||
on_accept();
|
on_accept();
|
||||||
m_reset_pulse = true;
|
m_reset_pulse = true;
|
||||||
play_cursor_sound = false;
|
play_cursor_sound = false;
|
||||||
|
|
@ -848,7 +848,7 @@ namespace rsx
|
||||||
}
|
}
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_oskcancel.wav");
|
play_sound(sound_effect::osk_cancel);
|
||||||
Close(CELL_OSKDIALOG_CLOSE_CANCEL);
|
Close(CELL_OSKDIALOG_CLOSE_CANCEL);
|
||||||
play_cursor_sound = false;
|
play_cursor_sound = false;
|
||||||
break;
|
break;
|
||||||
|
|
@ -890,7 +890,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
if (play_cursor_sound && (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default))
|
if (play_cursor_sound && (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default))
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_reset_pulse)
|
if (m_reset_pulse)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
#include "overlay_save_dialog.h"
|
#include "overlay_save_dialog.h"
|
||||||
#include "overlay_video.h"
|
#include "overlay_video.h"
|
||||||
#include "Utilities/date_time.h"
|
#include "Utilities/date_time.h"
|
||||||
#include "Emu/System.h"
|
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
|
|
@ -133,11 +132,11 @@ namespace rsx
|
||||||
if (m_no_saves)
|
if (m_no_saves)
|
||||||
break;
|
break;
|
||||||
return_code = m_list->get_selected_index();
|
return_code = m_list->get_selected_index();
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::dpad_up:
|
case pad_button::dpad_up:
|
||||||
|
|
@ -173,7 +172,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
#include "stdafx.h"
|
#include "stdafx.h"
|
||||||
#include "overlay_trophy_notification.h"
|
#include "overlay_trophy_notification.h"
|
||||||
#include "Emu/Cell/ErrorCodes.h"
|
#include "Emu/Cell/ErrorCodes.h"
|
||||||
#include "Emu/System.h"
|
|
||||||
|
|
||||||
namespace rsx
|
namespace rsx
|
||||||
{
|
{
|
||||||
|
|
@ -70,7 +69,7 @@ namespace rsx
|
||||||
{
|
{
|
||||||
// First tick
|
// First tick
|
||||||
creation_time_us = timestamp_us;
|
creation_time_us = timestamp_us;
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_trophy.wav");
|
play_sound(sound_effect::trophy);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -113,11 +113,11 @@ namespace rsx
|
||||||
{
|
{
|
||||||
return_code = selection_code::error;
|
return_code = selection_code::error;
|
||||||
}
|
}
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_decide.wav");
|
play_sound(sound_effect::accept);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::circle:
|
case pad_button::circle:
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cancel.wav");
|
play_sound(sound_effect::cancel);
|
||||||
close_dialog = true;
|
close_dialog = true;
|
||||||
break;
|
break;
|
||||||
case pad_button::dpad_up:
|
case pad_button::dpad_up:
|
||||||
|
|
@ -153,7 +153,7 @@ namespace rsx
|
||||||
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
// Play a sound unless this is a fast auto repeat which would induce a nasty noise
|
||||||
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
else if (!is_auto_repeat || m_auto_repeat_ms_interval >= m_auto_repeat_ms_interval_default)
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_cursor.wav");
|
play_sound(sound_effect::cursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,33 @@ namespace rsx
|
||||||
{
|
{
|
||||||
namespace overlays
|
namespace overlays
|
||||||
{
|
{
|
||||||
|
std::string get_sound_filepath(sound_effect sound)
|
||||||
|
{
|
||||||
|
const auto get_sound_filename = [sound]()
|
||||||
|
{
|
||||||
|
switch (sound)
|
||||||
|
{
|
||||||
|
case sound_effect::cursor: return "snd_cursor"sv;
|
||||||
|
case sound_effect::accept: return "snd_decide"sv;
|
||||||
|
case sound_effect::cancel: return "snd_cancel"sv;
|
||||||
|
case sound_effect::osk_accept: return "snd_oskenter"sv;
|
||||||
|
case sound_effect::osk_cancel: return "snd_oskcancel"sv;
|
||||||
|
case sound_effect::dialog_ok: return "snd_system_ok"sv;
|
||||||
|
case sound_effect::dialog_error: return "snd_system_ng"sv;
|
||||||
|
case sound_effect::trophy: return "snd_trophy"sv;
|
||||||
|
}
|
||||||
|
|
||||||
|
fmt::throw_exception("Unreachable (sound=%d)", static_cast<u32>(sound));
|
||||||
|
};
|
||||||
|
|
||||||
|
return fmt::format("%ssounds/%s.wav", fs::get_config_dir(), get_sound_filename());
|
||||||
|
}
|
||||||
|
|
||||||
|
void play_sound(sound_effect sound, std::optional<f32> volume)
|
||||||
|
{
|
||||||
|
Emu.GetCallbacks().play_sound(get_sound_filepath(sound), volume);
|
||||||
|
}
|
||||||
|
|
||||||
thread_local DECLARE(user_interface::g_thread_bit) = 0;
|
thread_local DECLARE(user_interface::g_thread_bit) = 0;
|
||||||
|
|
||||||
u32 user_interface::alloc_thread_bit()
|
u32 user_interface::alloc_thread_bit()
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,21 @@ namespace rsx
|
||||||
{
|
{
|
||||||
namespace overlays
|
namespace overlays
|
||||||
{
|
{
|
||||||
|
enum class sound_effect
|
||||||
|
{
|
||||||
|
cursor,
|
||||||
|
accept,
|
||||||
|
cancel,
|
||||||
|
osk_accept,
|
||||||
|
osk_cancel,
|
||||||
|
dialog_ok,
|
||||||
|
dialog_error,
|
||||||
|
trophy,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string get_sound_filepath(sound_effect sound);
|
||||||
|
void play_sound(sound_effect sound, std::optional<f32> volume = std::nullopt);
|
||||||
|
|
||||||
// Bitfield of UI signals to overlay manager
|
// Bitfield of UI signals to overlay manager
|
||||||
enum status_bits : u32
|
enum status_bits : u32
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -3073,7 +3073,7 @@ namespace rsx
|
||||||
{
|
{
|
||||||
capture_current_frame = false;
|
capture_current_frame = false;
|
||||||
|
|
||||||
std::string file_path = fs::get_config_dir() + "captures/" + Emu.GetTitleID() + "_" + date_time::current_time_narrow() + "_capture.rrc.gz";
|
const std::string file_path = fs::get_config_dir() + "captures/" + (Emu.GetTitleID().empty() ? Emu.GetTitle() : Emu.GetTitleID()) + "_" + date_time::current_time_narrow() + "_capture.rrc.gz";
|
||||||
|
|
||||||
fs::pending_file temp(file_path);
|
fs::pending_file temp(file_path);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -840,6 +840,19 @@ bool Emulator::BootRsxCapture(const std::string& path)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_path.clear();
|
||||||
|
m_path_old.clear();
|
||||||
|
m_path_original.clear();
|
||||||
|
m_title_id.clear();
|
||||||
|
m_title.clear();
|
||||||
|
m_localized_title.clear();
|
||||||
|
m_app_version.clear();
|
||||||
|
m_hash.clear();
|
||||||
|
m_cat.clear();
|
||||||
|
m_dir.clear();
|
||||||
|
m_sfo_dir.clear();
|
||||||
|
m_ar.reset();
|
||||||
|
|
||||||
Init();
|
Init();
|
||||||
g_cfg.video.disable_on_disk_shader_cache.set(true);
|
g_cfg.video.disable_on_disk_shader_cache.set(true);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,7 +101,7 @@ struct EmuCallbacks
|
||||||
std::function<std::string(localized_string_id, const char*)> get_localized_string;
|
std::function<std::string(localized_string_id, const char*)> get_localized_string;
|
||||||
std::function<std::u32string(localized_string_id, const char*)> get_localized_u32string;
|
std::function<std::u32string(localized_string_id, const char*)> get_localized_u32string;
|
||||||
std::function<std::string(const cfg::_base*, u32)> get_localized_setting;
|
std::function<std::string(const cfg::_base*, u32)> get_localized_setting;
|
||||||
std::function<void(const std::string&)> play_sound;
|
std::function<void(const std::string&, std::optional<f32>)> play_sound;
|
||||||
std::function<bool(const std::string&, std::string&, s32&, s32&, s32&)> get_image_info; // (filename, sub_type, width, height, CellSearchOrientation)
|
std::function<bool(const std::string&, std::string&, s32&, s32&, s32&)> get_image_info; // (filename, sub_type, width, height, CellSearchOrientation)
|
||||||
std::function<bool(const std::string&, s32, s32, s32&, s32&, u8*, bool)> get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit)
|
std::function<bool(const std::string&, s32, s32, s32&, s32&, u8*, bool)> get_scaled_image; // (filename, target_width, target_height, width, height, dst, force_fit)
|
||||||
std::string(*resolve_path)(std::string_view) = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt
|
std::string(*resolve_path)(std::string_view) = [](std::string_view arg){ return std::string{arg}; }; // Resolve path using Qt
|
||||||
|
|
|
||||||
|
|
@ -169,7 +169,7 @@ void headless_application::InitializeCallbacks()
|
||||||
callbacks.get_localized_u32string = [](localized_string_id, const char*) -> std::u32string { return {}; };
|
callbacks.get_localized_u32string = [](localized_string_id, const char*) -> std::u32string { return {}; };
|
||||||
callbacks.get_localized_setting = [](const cfg::_base*, u32) -> std::string { return {}; };
|
callbacks.get_localized_setting = [](const cfg::_base*, u32) -> std::string { return {}; };
|
||||||
|
|
||||||
callbacks.play_sound = [](const std::string&){};
|
callbacks.play_sound = [](const std::string&, std::optional<f32>){};
|
||||||
callbacks.add_breakpoint = [](u32 /*addr*/){};
|
callbacks.add_breakpoint = [](u32 /*addr*/){};
|
||||||
|
|
||||||
callbacks.display_sleep_control_supported = [](){ return false; };
|
callbacks.display_sleep_control_supported = [](){ return false; };
|
||||||
|
|
|
||||||
|
|
@ -430,6 +430,9 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_preview.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_screenshot_preview.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_sound_effect_manager_dialog.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Debug\moc_sendmessage_dialog_frame.cpp">
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_sendmessage_dialog_frame.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -718,6 +721,9 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_preview.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_preview.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Release\moc_sound_effect_manager_dialog.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_sendmessage_dialog_frame.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_sendmessage_dialog_frame.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -851,6 +857,7 @@
|
||||||
<ClCompile Include="rpcs3qt\screenshot_item.cpp" />
|
<ClCompile Include="rpcs3qt\screenshot_item.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\screenshot_manager_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
|
<ClCompile Include="rpcs3qt\screenshot_preview.cpp" />
|
||||||
|
<ClCompile Include="rpcs3qt\sound_effect_manager_dialog.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp" />
|
<ClCompile Include="rpcs3qt\sendmessage_dialog_frame.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\settings.cpp" />
|
<ClCompile Include="rpcs3qt\settings.cpp" />
|
||||||
<ClCompile Include="rpcs3qt\shortcut_dialog.cpp" />
|
<ClCompile Include="rpcs3qt\shortcut_dialog.cpp" />
|
||||||
|
|
@ -1311,6 +1318,16 @@
|
||||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="rpcs3qt\sound_effect_manager_dialog.h">
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\debug" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||||
|
<Message Condition="'$(Configuration)|$(Platform)'=='Release|x64'">Moc%27ing %(Identity)...</Message>
|
||||||
|
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp</Outputs>
|
||||||
|
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(QTDIR)\bin\moc.exe" "%(FullPath)" -o ".\QTGeneratedFiles\$(ConfigurationName)\moc_%(Filename).cpp" -D_WINDOWS -DUNICODE -DWIN32 -DWIN64 -DWITH_DISCORD_RPC -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DNDEBUG -DQT_CONCURRENT_LIB -D%(PreprocessorDefinitions) "-I.\..\3rdparty\wolfssl\wolfssl" "-I.\..\3rdparty\curl\curl\include" "-I.\..\3rdparty\libusb\libusb\libusb" "-I$(VULKAN_SDK)\Include" "-I$(QTDIR)\include" "-I$(QTDIR)\include\QtWidgets" "-I$(QTDIR)\include\QtGui" "-I$(QTDIR)\include\QtCore" "-I.\release" "-I.\QTGeneratedFiles\$(ConfigurationName)" "-I.\QTGeneratedFiles" "-I$(QTDIR)\include\QtConcurrent"</Command>
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="rpcs3qt\fatal_error_dialog.h">
|
<CustomBuild Include="rpcs3qt\fatal_error_dialog.h">
|
||||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||||
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
<Message Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">Moc%27ing %(Identity)...</Message>
|
||||||
|
|
|
||||||
|
|
@ -205,6 +205,9 @@
|
||||||
<Filter Include="Gui\widgets">
|
<Filter Include="Gui\widgets">
|
||||||
<UniqueIdentifier>{149c596b-83e7-43f8-b5db-6108694434ef}</UniqueIdentifier>
|
<UniqueIdentifier>{149c596b-83e7-43f8-b5db-6108694434ef}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
|
<Filter Include="Gui\sound effect manager">
|
||||||
|
<UniqueIdentifier>{640b7d83-1522-4384-8bf7-a4fbd5873ae7}</UniqueIdentifier>
|
||||||
|
</Filter>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="main.cpp">
|
<ClCompile Include="main.cpp">
|
||||||
|
|
@ -738,6 +741,15 @@
|
||||||
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_manager_dialog.cpp">
|
<ClCompile Include="QTGeneratedFiles\Release\moc_screenshot_manager_dialog.cpp">
|
||||||
<Filter>Generated Files\Release</Filter>
|
<Filter>Generated Files\Release</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="rpcs3qt\sound_effect_manager_dialog.cpp">
|
||||||
|
<Filter>Gui\sound effect manager</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Debug\moc_sound_effect_manager_dialog.cpp">
|
||||||
|
<Filter>Generated Files\Debug</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="QTGeneratedFiles\Release\moc_sound_effect_manager_dialog.cpp">
|
||||||
|
<Filter>Generated Files\Release</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="rpcs3qt\screenshot_preview.cpp">
|
<ClCompile Include="rpcs3qt\screenshot_preview.cpp">
|
||||||
<Filter>Gui\screenshot manager</Filter>
|
<Filter>Gui\screenshot manager</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
@ -1627,6 +1639,9 @@
|
||||||
<CustomBuild Include="rpcs3qt\screenshot_preview.h">
|
<CustomBuild Include="rpcs3qt\screenshot_preview.h">
|
||||||
<Filter>Gui\screenshot manager</Filter>
|
<Filter>Gui\screenshot manager</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
<CustomBuild Include="rpcs3qt\sound_effect_manager_dialog.h">
|
||||||
|
<Filter>Gui\sound effect manager</Filter>
|
||||||
|
</CustomBuild>
|
||||||
<CustomBuild Include="rpcs3qt\dimensions_dialog.h">
|
<CustomBuild Include="rpcs3qt\dimensions_dialog.h">
|
||||||
<Filter>Gui\dimensions</Filter>
|
<Filter>Gui\dimensions</Filter>
|
||||||
</CustomBuild>
|
</CustomBuild>
|
||||||
|
|
|
||||||
|
|
@ -99,6 +99,7 @@ add_library(rpcs3_ui STATIC
|
||||||
shortcut_handler.cpp
|
shortcut_handler.cpp
|
||||||
shortcut_settings.cpp
|
shortcut_settings.cpp
|
||||||
skylander_dialog.cpp
|
skylander_dialog.cpp
|
||||||
|
sound_effect_manager_dialog.cpp
|
||||||
syntax_highlighter.cpp
|
syntax_highlighter.cpp
|
||||||
system_cmd_dialog.cpp
|
system_cmd_dialog.cpp
|
||||||
table_item_delegate.cpp
|
table_item_delegate.cpp
|
||||||
|
|
|
||||||
|
|
@ -668,10 +668,9 @@ void emu_settings::EnhanceSpinBox(QSpinBox* spinbox, emu_settings_type type, con
|
||||||
spinbox->setRange(min, max);
|
spinbox->setRange(min, max);
|
||||||
spinbox->setValue(val);
|
spinbox->setValue(val);
|
||||||
|
|
||||||
connect(spinbox, &QSpinBox::textChanged, this, [type, spinbox, this](const QString& /* text*/)
|
connect(spinbox, &QSpinBox::valueChanged, this, [type, this](int value)
|
||||||
{
|
{
|
||||||
if (!spinbox) return;
|
SetSetting(type, fmt::format("%d", value));
|
||||||
SetSetting(type, spinbox->cleanText().toStdString());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &emu_settings::RestoreDefaultsSignal, spinbox, [def, spinbox]()
|
connect(this, &emu_settings::RestoreDefaultsSignal, spinbox, [def, spinbox]()
|
||||||
|
|
@ -724,10 +723,9 @@ void emu_settings::EnhanceDoubleSpinBox(QDoubleSpinBox* spinbox, emu_settings_ty
|
||||||
spinbox->setRange(min, max);
|
spinbox->setRange(min, max);
|
||||||
spinbox->setValue(val);
|
spinbox->setValue(val);
|
||||||
|
|
||||||
connect(spinbox, &QDoubleSpinBox::textChanged, this, [type, spinbox, this](const QString& /* text*/)
|
connect(spinbox, &QDoubleSpinBox::valueChanged, this, [type, this](double value)
|
||||||
{
|
{
|
||||||
if (!spinbox) return;
|
SetSetting(type, fmt::format("%f", value));
|
||||||
SetSetting(type, spinbox->cleanText().toStdString());
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(this, &emu_settings::RestoreDefaultsSignal, spinbox, [def, spinbox]()
|
connect(this, &emu_settings::RestoreDefaultsSignal, spinbox, [def, spinbox]()
|
||||||
|
|
|
||||||
|
|
@ -14,16 +14,16 @@ game_list::game_list() : QTableWidget(), game_list_base()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list::sync_header_actions(QList<QAction*>& actions, std::function<bool(int)> get_visibility)
|
void game_list::sync_header_actions(std::map<int, QAction*>& actions, std::function<bool(int)> get_visibility)
|
||||||
{
|
{
|
||||||
ensure(get_visibility);
|
ensure(get_visibility);
|
||||||
|
|
||||||
bool is_dirty = false;
|
bool is_dirty = false;
|
||||||
|
|
||||||
for (int col = 0; col < actions.count(); ++col)
|
for (auto& [col, action] : actions)
|
||||||
{
|
{
|
||||||
const bool is_hidden = !get_visibility(col);
|
const bool is_hidden = !get_visibility(col);
|
||||||
actions[col]->setChecked(!is_hidden);
|
action->setChecked(!is_hidden);
|
||||||
|
|
||||||
if (isColumnHidden(col) != is_hidden)
|
if (isColumnHidden(col) != is_hidden)
|
||||||
{
|
{
|
||||||
|
|
@ -38,7 +38,7 @@ void game_list::sync_header_actions(QList<QAction*>& actions, std::function<bool
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list::create_header_actions(QList<QAction*>& actions, std::function<bool(int)> get_visibility, std::function<void(int, bool)> set_visibility)
|
void game_list::create_header_actions(std::map<int, QAction*>& actions, std::function<bool(int)> get_visibility, std::function<void(int, bool)> set_visibility)
|
||||||
{
|
{
|
||||||
ensure(get_visibility);
|
ensure(get_visibility);
|
||||||
ensure(set_visibility);
|
ensure(set_visibility);
|
||||||
|
|
@ -48,27 +48,30 @@ void game_list::create_header_actions(QList<QAction*>& actions, std::function<bo
|
||||||
connect(horizontalHeader(), &QHeaderView::customContextMenuRequested, this, [this, &actions](const QPoint& pos)
|
connect(horizontalHeader(), &QHeaderView::customContextMenuRequested, this, [this, &actions](const QPoint& pos)
|
||||||
{
|
{
|
||||||
QMenu* configure = new QMenu(this);
|
QMenu* configure = new QMenu(this);
|
||||||
configure->addActions(actions);
|
for (auto& [col, action] : actions)
|
||||||
|
{
|
||||||
|
configure->addAction(action);
|
||||||
|
}
|
||||||
configure->exec(horizontalHeader()->viewport()->mapToGlobal(pos));
|
configure->exec(horizontalHeader()->viewport()->mapToGlobal(pos));
|
||||||
});
|
});
|
||||||
|
|
||||||
for (int col = 0; col < actions.count(); ++col)
|
for (auto& [col, action] : actions)
|
||||||
{
|
{
|
||||||
actions[col]->setCheckable(true);
|
action->setCheckable(true);
|
||||||
|
|
||||||
connect(actions[col], &QAction::triggered, this, [this, &actions, get_visibility, set_visibility, col](bool checked)
|
connect(action, &QAction::triggered, this, [this, &actions, get_visibility, set_visibility, col](bool checked)
|
||||||
{
|
{
|
||||||
if (!checked) // be sure to have at least one column left so you can call the context menu at all time
|
if (!checked) // be sure to have at least one column left so you can call the context menu at all time
|
||||||
{
|
{
|
||||||
int c = 0;
|
int c = 0;
|
||||||
for (int i = 0; i < actions.count(); ++i)
|
for (auto& [col, action] : actions)
|
||||||
{
|
{
|
||||||
if (get_visibility(i) && ++c > 1)
|
if (get_visibility(col) && ++c > 1)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (c < 2)
|
if (c < 2)
|
||||||
{
|
{
|
||||||
actions[col]->setChecked(true); // re-enable the checkbox if we don't change the actual state
|
::at32(actions, col)->setChecked(true); // re-enable the checkbox if we don't change the actual state
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,8 @@ class game_list : public QTableWidget, public game_list_base
|
||||||
public:
|
public:
|
||||||
game_list();
|
game_list();
|
||||||
|
|
||||||
void sync_header_actions(QList<QAction*>& actions, std::function<bool(int)> get_visibility);
|
void sync_header_actions(std::map<int, QAction*>& actions, std::function<bool(int)> get_visibility);
|
||||||
void create_header_actions(QList<QAction*>& actions, std::function<bool(int)> get_visibility, std::function<void(int, bool)> set_visibility);
|
void create_header_actions(std::map<int, QAction*>& actions, std::function<bool(int)> get_visibility, std::function<void(int, bool)> set_visibility);
|
||||||
|
|
||||||
void clear_list() override; // Use this instead of clearContents
|
void clear_list() override; // Use this instead of clearContents
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,27 +100,28 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
m_game_dock->setCentralWidget(m_central_widget);
|
m_game_dock->setCentralWidget(m_central_widget);
|
||||||
|
|
||||||
// Actions regarding showing/hiding columns
|
// Actions regarding showing/hiding columns
|
||||||
auto add_column = [this](gui::game_list_columns col, const QString& header_text, const QString& action_text)
|
const auto add_column = [this](gui::game_list_columns col)
|
||||||
{
|
{
|
||||||
m_game_list->setHorizontalHeaderItem(static_cast<int>(col), new QTableWidgetItem(header_text));
|
const int column = static_cast<int>(col);
|
||||||
m_columnActs.append(new QAction(action_text, this));
|
m_game_list->setHorizontalHeaderItem(column, new QTableWidgetItem(get_header_text(column)));
|
||||||
|
m_column_acts[column] = new QAction(get_action_text(column), this);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_column(gui::game_list_columns::icon, tr("Icon"), tr("Show Icons"));
|
add_column(gui::game_list_columns::icon);
|
||||||
add_column(gui::game_list_columns::name, tr("Name"), tr("Show Names"));
|
add_column(gui::game_list_columns::name);
|
||||||
add_column(gui::game_list_columns::serial, tr("Serial"), tr("Show Serials"));
|
add_column(gui::game_list_columns::serial);
|
||||||
add_column(gui::game_list_columns::firmware, tr("Firmware"), tr("Show Firmwares"));
|
add_column(gui::game_list_columns::firmware);
|
||||||
add_column(gui::game_list_columns::version, tr("Version"), tr("Show Versions"));
|
add_column(gui::game_list_columns::version);
|
||||||
add_column(gui::game_list_columns::category, tr("Category"), tr("Show Categories"));
|
add_column(gui::game_list_columns::category);
|
||||||
add_column(gui::game_list_columns::path, tr("Path"), tr("Show Paths"));
|
add_column(gui::game_list_columns::path);
|
||||||
add_column(gui::game_list_columns::move, tr("PlayStation Move"), tr("Show PlayStation Move"));
|
add_column(gui::game_list_columns::move);
|
||||||
add_column(gui::game_list_columns::resolution, tr("Supported Resolutions"), tr("Show Supported Resolutions"));
|
add_column(gui::game_list_columns::resolution);
|
||||||
add_column(gui::game_list_columns::sound, tr("Sound Formats"), tr("Show Sound Formats"));
|
add_column(gui::game_list_columns::sound);
|
||||||
add_column(gui::game_list_columns::parental, tr("Parental Level"), tr("Show Parental Levels"));
|
add_column(gui::game_list_columns::parental);
|
||||||
add_column(gui::game_list_columns::last_play, tr("Last Played"), tr("Show Last Played"));
|
add_column(gui::game_list_columns::last_play);
|
||||||
add_column(gui::game_list_columns::playtime, tr("Time Played"), tr("Show Time Played"));
|
add_column(gui::game_list_columns::playtime);
|
||||||
add_column(gui::game_list_columns::compat, tr("Compatibility"), tr("Show Compatibility"));
|
add_column(gui::game_list_columns::compat);
|
||||||
add_column(gui::game_list_columns::dir_size, tr("Space On Disk"), tr("Show Space On Disk"));
|
add_column(gui::game_list_columns::dir_size);
|
||||||
|
|
||||||
m_progress_dialog = new progress_dialog(tr("Loading games"), tr("Loading games, please wait..."), tr("Cancel"), 0, 0, false, this, Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
|
m_progress_dialog = new progress_dialog(tr("Loading games"), tr("Loading games, please wait..."), tr("Cancel"), 0, 0, false, this, Qt::Dialog | Qt::WindowTitleHint | Qt::CustomizeWindowHint);
|
||||||
m_progress_dialog->setMinimumDuration(200); // Only show the progress dialog after some time has passed
|
m_progress_dialog->setMinimumDuration(200); // Only show the progress dialog after some time has passed
|
||||||
|
|
@ -211,7 +212,7 @@ game_list_frame::game_list_frame(std::shared_ptr<gui_settings> gui_settings, std
|
||||||
connect(m_game_list, &game_list::FocusToSearchBar, this, &game_list_frame::FocusToSearchBar);
|
connect(m_game_list, &game_list::FocusToSearchBar, this, &game_list_frame::FocusToSearchBar);
|
||||||
connect(m_game_grid, &game_list_grid::FocusToSearchBar, this, &game_list_frame::FocusToSearchBar);
|
connect(m_game_grid, &game_list_grid::FocusToSearchBar, this, &game_list_frame::FocusToSearchBar);
|
||||||
|
|
||||||
m_game_list->create_header_actions(m_columnActs,
|
m_game_list->create_header_actions(m_column_acts,
|
||||||
[this](int col) { return m_gui_settings->GetGamelistColVisibility(static_cast<gui::game_list_columns>(col)); },
|
[this](int col) { return m_gui_settings->GetGamelistColVisibility(static_cast<gui::game_list_columns>(col)); },
|
||||||
[this](int col, bool visible) { m_gui_settings->SetGamelistColVisibility(static_cast<gui::game_list_columns>(col), visible); });
|
[this](int col, bool visible) { m_gui_settings->SetGamelistColVisibility(static_cast<gui::game_list_columns>(col), visible); });
|
||||||
}
|
}
|
||||||
|
|
@ -227,7 +228,7 @@ void game_list_frame::LoadSettings()
|
||||||
m_show_custom_icons = m_gui_settings->GetValue(gui::gl_custom_icon).toBool();
|
m_show_custom_icons = m_gui_settings->GetValue(gui::gl_custom_icon).toBool();
|
||||||
m_play_hover_movies = m_gui_settings->GetValue(gui::gl_hover_gifs).toBool();
|
m_play_hover_movies = m_gui_settings->GetValue(gui::gl_hover_gifs).toBool();
|
||||||
|
|
||||||
m_game_list->sync_header_actions(m_columnActs, [this](int col) { return m_gui_settings->GetGamelistColVisibility(static_cast<gui::game_list_columns>(col)); });
|
m_game_list->sync_header_actions(m_column_acts, [this](int col) { return m_gui_settings->GetGamelistColVisibility(static_cast<gui::game_list_columns>(col)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
game_list_frame::~game_list_frame()
|
game_list_frame::~game_list_frame()
|
||||||
|
|
@ -238,6 +239,54 @@ game_list_frame::~game_list_frame()
|
||||||
gui::utils::stop_future_watcher(m_refresh_watcher, true);
|
gui::utils::stop_future_watcher(m_refresh_watcher, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString game_list_frame::get_header_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::game_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::game_list_columns::icon: return tr("Icon");
|
||||||
|
case gui::game_list_columns::name: return tr("Name");
|
||||||
|
case gui::game_list_columns::serial: return tr("Serial");
|
||||||
|
case gui::game_list_columns::firmware: return tr("Firmware");
|
||||||
|
case gui::game_list_columns::version: return tr("Version");
|
||||||
|
case gui::game_list_columns::category: return tr("Category");
|
||||||
|
case gui::game_list_columns::path: return tr("Path");
|
||||||
|
case gui::game_list_columns::move: return tr("PlayStation Move");
|
||||||
|
case gui::game_list_columns::resolution: return tr("Supported Resolutions");
|
||||||
|
case gui::game_list_columns::sound: return tr("Sound Formats");
|
||||||
|
case gui::game_list_columns::parental: return tr("Parental Level");
|
||||||
|
case gui::game_list_columns::last_play: return tr("Last Played");
|
||||||
|
case gui::game_list_columns::playtime: return tr("Time Played");
|
||||||
|
case gui::game_list_columns::compat: return tr("Compatibility");
|
||||||
|
case gui::game_list_columns::dir_size: return tr("Space On Disk");
|
||||||
|
case gui::game_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString game_list_frame::get_action_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::game_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::game_list_columns::icon: return tr("Show Icons");
|
||||||
|
case gui::game_list_columns::name: return tr("Show Names");
|
||||||
|
case gui::game_list_columns::serial: return tr("Show Serials");
|
||||||
|
case gui::game_list_columns::firmware: return tr("Show Firmwares");
|
||||||
|
case gui::game_list_columns::version: return tr("Show Versions");
|
||||||
|
case gui::game_list_columns::category: return tr("Show Categories");
|
||||||
|
case gui::game_list_columns::path: return tr("Show Paths");
|
||||||
|
case gui::game_list_columns::move: return tr("Show PlayStation Move");
|
||||||
|
case gui::game_list_columns::resolution: return tr("Show Supported Resolutions");
|
||||||
|
case gui::game_list_columns::sound: return tr("Show Sound Formats");
|
||||||
|
case gui::game_list_columns::parental: return tr("Show Parental Levels");
|
||||||
|
case gui::game_list_columns::last_play: return tr("Show Last Played");
|
||||||
|
case gui::game_list_columns::playtime: return tr("Show Time Played");
|
||||||
|
case gui::game_list_columns::compat: return tr("Show Compatibility");
|
||||||
|
case gui::game_list_columns::dir_size: return tr("Show Space On Disk");
|
||||||
|
case gui::game_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void game_list_frame::OnColClicked(int col)
|
void game_list_frame::OnColClicked(int col)
|
||||||
{
|
{
|
||||||
if (col == static_cast<int>(gui::game_list_columns::icon)) return; // Don't "sort" icons.
|
if (col == static_cast<int>(gui::game_list_columns::icon)) return; // Don't "sort" icons.
|
||||||
|
|
@ -417,6 +466,21 @@ void game_list_frame::Refresh(const bool from_drive, const std::vector<std::stri
|
||||||
m_progress_dialog->SetValue(0);
|
m_progress_dialog->SetValue(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update headers
|
||||||
|
for (int col = 0; col < m_game_list->horizontalHeader()->count(); col++)
|
||||||
|
{
|
||||||
|
if (auto item = m_game_list->horizontalHeaderItem(col))
|
||||||
|
{
|
||||||
|
item->setText(get_header_text(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update actions
|
||||||
|
for (auto& [col, action] : m_column_acts)
|
||||||
|
{
|
||||||
|
action->setText(get_action_text(col));
|
||||||
|
}
|
||||||
|
|
||||||
const std::string games_dir = rpcs3::utils::get_games_dir();
|
const std::string games_dir = rpcs3::utils::get_games_dir();
|
||||||
|
|
||||||
// Remove the specified and detected serials (title id) belonging to "games_dir" folder only from the game list in memory
|
// Remove the specified and detected serials (title id) belonging to "games_dir" folder only from the game list in memory
|
||||||
|
|
@ -920,7 +984,7 @@ void game_list_frame::OnRefreshFinished()
|
||||||
if (!std::exchange(m_initial_refresh_done, true))
|
if (!std::exchange(m_initial_refresh_done, true))
|
||||||
{
|
{
|
||||||
m_game_list->restore_layout(m_gui_settings->GetValue(gui::gl_state).toByteArray());
|
m_game_list->restore_layout(m_gui_settings->GetValue(gui::gl_state).toByteArray());
|
||||||
m_game_list->sync_header_actions(m_columnActs, [this](int col) { return m_gui_settings->GetGamelistColVisibility(static_cast<gui::game_list_columns>(col)); });
|
m_game_list->sync_header_actions(m_column_acts, [this](int col) { return m_gui_settings->GetGamelistColVisibility(static_cast<gui::game_list_columns>(col)); });
|
||||||
}
|
}
|
||||||
|
|
||||||
// Emit signal and remove slots
|
// Emit signal and remove slots
|
||||||
|
|
@ -959,9 +1023,9 @@ void game_list_frame::ToggleCategoryFilter(const QStringList& categories, bool s
|
||||||
|
|
||||||
void game_list_frame::SaveSettings()
|
void game_list_frame::SaveSettings()
|
||||||
{
|
{
|
||||||
for (int col = 0; col < m_columnActs.count(); ++col)
|
for (const auto& [col, action] : m_column_acts)
|
||||||
{
|
{
|
||||||
m_gui_settings->SetGamelistColVisibility(static_cast<gui::game_list_columns>(col), m_columnActs[col]->isChecked());
|
m_gui_settings->SetGamelistColVisibility(static_cast<gui::game_list_columns>(col), action->isChecked());
|
||||||
}
|
}
|
||||||
m_gui_settings->SetValue(gui::gl_sortCol, m_sort_column, false);
|
m_gui_settings->SetValue(gui::gl_sortCol, m_sort_column, false);
|
||||||
m_gui_settings->SetValue(gui::gl_sortAsc, m_col_sort_order == Qt::AscendingOrder, false);
|
m_gui_settings->SetValue(gui::gl_sortAsc, m_col_sort_order == Qt::AscendingOrder, false);
|
||||||
|
|
@ -2704,7 +2768,7 @@ void game_list_frame::ShowCustomConfigIcon(const game_info& game)
|
||||||
RepaintIcons();
|
RepaintIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list_frame::ResizeIcons(const int& slider_pos)
|
void game_list_frame::ResizeIcons(int slider_pos)
|
||||||
{
|
{
|
||||||
m_icon_size_index = slider_pos;
|
m_icon_size_index = slider_pos;
|
||||||
m_icon_size = gui_settings::SizeFromSlider(slider_pos);
|
m_icon_size = gui_settings::SizeFromSlider(slider_pos);
|
||||||
|
|
@ -2712,7 +2776,7 @@ void game_list_frame::ResizeIcons(const int& slider_pos)
|
||||||
RepaintIcons();
|
RepaintIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list_frame::RepaintIcons(const bool& from_settings)
|
void game_list_frame::RepaintIcons(bool from_settings)
|
||||||
{
|
{
|
||||||
gui::utils::stop_future_watcher(m_parsing_watcher, false);
|
gui::utils::stop_future_watcher(m_parsing_watcher, false);
|
||||||
gui::utils::stop_future_watcher(m_refresh_watcher, false);
|
gui::utils::stop_future_watcher(m_refresh_watcher, false);
|
||||||
|
|
@ -2746,7 +2810,7 @@ void game_list_frame::SetShowHidden(bool show)
|
||||||
m_show_hidden = show;
|
m_show_hidden = show;
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_list_frame::SetListMode(const bool& is_list)
|
void game_list_frame::SetListMode(bool is_list)
|
||||||
{
|
{
|
||||||
m_old_layout_is_list = m_is_list_layout;
|
m_old_layout_is_list = m_is_list_layout;
|
||||||
m_is_list_layout = is_list;
|
m_is_list_layout = is_list;
|
||||||
|
|
|
||||||
|
|
@ -48,10 +48,10 @@ public:
|
||||||
void SaveSettings();
|
void SaveSettings();
|
||||||
|
|
||||||
/** Resize Gamelist Icons to size given by slider position */
|
/** Resize Gamelist Icons to size given by slider position */
|
||||||
void ResizeIcons(const int& slider_pos);
|
void ResizeIcons(int slider_pos);
|
||||||
|
|
||||||
/** Repaint Gamelist Icons with new background color */
|
/** Repaint Gamelist Icons with new background color */
|
||||||
void RepaintIcons(const bool& from_settings = false);
|
void RepaintIcons(bool from_settings = false);
|
||||||
|
|
||||||
void SetShowHidden(bool show);
|
void SetShowHidden(bool show);
|
||||||
|
|
||||||
|
|
@ -70,7 +70,7 @@ public Q_SLOTS:
|
||||||
void BatchRemoveCustomConfigurations();
|
void BatchRemoveCustomConfigurations();
|
||||||
void BatchRemoveCustomPadConfigurations();
|
void BatchRemoveCustomPadConfigurations();
|
||||||
void BatchRemoveShaderCaches();
|
void BatchRemoveShaderCaches();
|
||||||
void SetListMode(const bool& is_list);
|
void SetListMode(bool is_list);
|
||||||
void SetSearchText(const QString& text);
|
void SetSearchText(const QString& text);
|
||||||
void SetShowCompatibilityInGrid(bool show);
|
void SetShowCompatibilityInGrid(bool show);
|
||||||
void SetPreferGameDataIcons(bool enabled);
|
void SetPreferGameDataIcons(bool enabled);
|
||||||
|
|
@ -91,7 +91,7 @@ Q_SIGNALS:
|
||||||
void GameListFrameClosed();
|
void GameListFrameClosed();
|
||||||
void NotifyGameSelection(const game_info& game);
|
void NotifyGameSelection(const game_info& game);
|
||||||
void RequestBoot(const game_info& game, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "", const std::string& savestate = "");
|
void RequestBoot(const game_info& game, cfg_mode config_mode = cfg_mode::custom, const std::string& config_path = "", const std::string& savestate = "");
|
||||||
void RequestIconSizeChange(const int& val);
|
void RequestIconSizeChange(int val);
|
||||||
void NotifyEmuSettingsChange();
|
void NotifyEmuSettingsChange();
|
||||||
void FocusToSearchBar();
|
void FocusToSearchBar();
|
||||||
void Refreshed();
|
void Refreshed();
|
||||||
|
|
@ -127,6 +127,9 @@ protected:
|
||||||
private:
|
private:
|
||||||
void push_path(const std::string& path, std::vector<std::string>& legit_paths);
|
void push_path(const std::string& path, std::vector<std::string>& legit_paths);
|
||||||
|
|
||||||
|
QString get_header_text(int col) const;
|
||||||
|
QString get_action_text(int col) const;
|
||||||
|
|
||||||
void ShowCustomConfigIcon(const game_info& game);
|
void ShowCustomConfigIcon(const game_info& game);
|
||||||
bool SearchMatchesApp(const QString& name, const QString& serial, bool fallback = false) const;
|
bool SearchMatchesApp(const QString& name, const QString& serial, bool fallback = false) const;
|
||||||
|
|
||||||
|
|
@ -165,7 +168,7 @@ private:
|
||||||
game_list_table* m_game_list = nullptr;
|
game_list_table* m_game_list = nullptr;
|
||||||
game_compatibility* m_game_compat = nullptr;
|
game_compatibility* m_game_compat = nullptr;
|
||||||
progress_dialog* m_progress_dialog = nullptr;
|
progress_dialog* m_progress_dialog = nullptr;
|
||||||
QList<QAction*> m_columnActs;
|
std::map<int, QAction*> m_column_acts;
|
||||||
Qt::SortOrder m_col_sort_order{};
|
Qt::SortOrder m_col_sort_order{};
|
||||||
int m_sort_column{};
|
int m_sort_column{};
|
||||||
bool m_initial_refresh_done = false;
|
bool m_initial_refresh_done = false;
|
||||||
|
|
|
||||||
|
|
@ -447,7 +447,7 @@ void gs_frame::toggle_recording()
|
||||||
// Play a sound
|
// Play a sound
|
||||||
if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_recording.wav"; fs::is_file(sound_path))
|
if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_recording.wav"; fs::is_file(sound_path))
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(sound_path);
|
Emu.GetCallbacks().play_sound(sound_path, std::nullopt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -1070,7 +1070,7 @@ void gs_frame::take_screenshot(std::vector<u8>&& data, u32 sshot_width, u32 ssho
|
||||||
{
|
{
|
||||||
if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_screenshot.wav"; fs::is_file(sound_path))
|
if (const std::string sound_path = fs::get_config_dir() + "sounds/snd_screenshot.wav"; fs::is_file(sound_path))
|
||||||
{
|
{
|
||||||
Emu.GetCallbacks().play_sound(sound_path);
|
Emu.GetCallbacks().play_sound(sound_path, std::nullopt);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -743,9 +743,9 @@ void gui_application::InitializeCallbacks()
|
||||||
return m_emu_settings->GetLocalizedSetting(node, enum_index);
|
return m_emu_settings->GetLocalizedSetting(node, enum_index);
|
||||||
};
|
};
|
||||||
|
|
||||||
callbacks.play_sound = [this](const std::string& path)
|
callbacks.play_sound = [this](const std::string& path, std::optional<f32> volume)
|
||||||
{
|
{
|
||||||
Emu.CallFromMainThread([this, path]()
|
Emu.CallFromMainThread([this, path, volume]()
|
||||||
{
|
{
|
||||||
if (fs::is_file(path))
|
if (fs::is_file(path))
|
||||||
{
|
{
|
||||||
|
|
@ -758,12 +758,12 @@ void gui_application::InitializeCallbacks()
|
||||||
// Create a new sound effect. Re-using the same object seems to be broken for some users starting with Qt 6.6.3.
|
// Create a new sound effect. Re-using the same object seems to be broken for some users starting with Qt 6.6.3.
|
||||||
std::unique_ptr<QSoundEffect> sound_effect = std::make_unique<QSoundEffect>();
|
std::unique_ptr<QSoundEffect> sound_effect = std::make_unique<QSoundEffect>();
|
||||||
sound_effect->setSource(QUrl::fromLocalFile(QString::fromStdString(path)));
|
sound_effect->setSource(QUrl::fromLocalFile(QString::fromStdString(path)));
|
||||||
sound_effect->setVolume(audio::get_volume());
|
sound_effect->setVolume(volume ? *volume : audio::get_volume());
|
||||||
sound_effect->play();
|
sound_effect->play();
|
||||||
|
|
||||||
m_sound_effects.push_back(std::move(sound_effect));
|
m_sound_effects.push_back(std::move(sound_effect));
|
||||||
}
|
}
|
||||||
});
|
}, nullptr, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (m_show_gui) // If this is false, we already have a fallback in the main_application.
|
if (m_show_gui) // If this is false, we already have a fallback in the main_application.
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
#include "vfs_tool_dialog.h"
|
#include "vfs_tool_dialog.h"
|
||||||
#include "welcome_dialog.h"
|
#include "welcome_dialog.h"
|
||||||
#include "music_player_dialog.h"
|
#include "music_player_dialog.h"
|
||||||
|
#include "sound_effect_manager_dialog.h"
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
|
@ -2343,6 +2344,8 @@ void main_window::RetranslateUI(const QStringList& language_codes, const QString
|
||||||
{
|
{
|
||||||
m_game_list_frame->Refresh(true);
|
m_game_list_frame->Refresh(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_EMIT RequestDialogRepaint();
|
||||||
}
|
}
|
||||||
|
|
||||||
void main_window::ShowTitleBars(bool show) const
|
void main_window::ShowTitleBars(bool show) const
|
||||||
|
|
@ -3053,6 +3056,12 @@ void main_window::CreateConnects()
|
||||||
screenshot_manager->show();
|
screenshot_manager->show();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
connect(ui->actionManage_SoundEffects, &QAction::triggered, this, [this]
|
||||||
|
{
|
||||||
|
sound_effect_manager_dialog* dlg = new sound_effect_manager_dialog();
|
||||||
|
dlg->show();
|
||||||
|
});
|
||||||
|
|
||||||
connect(ui->toolsCgDisasmAct, &QAction::triggered, this, [this]
|
connect(ui->toolsCgDisasmAct, &QAction::triggered, this, [this]
|
||||||
{
|
{
|
||||||
cg_disasm_window* cgdw = new cg_disasm_window(m_gui_settings);
|
cg_disasm_window* cgdw = new cg_disasm_window(m_gui_settings);
|
||||||
|
|
@ -3336,7 +3345,7 @@ void main_window::CreateConnects()
|
||||||
connect(ui->showCustomIconsAct, &QAction::triggered, m_game_list_frame, &game_list_frame::SetShowCustomIcons);
|
connect(ui->showCustomIconsAct, &QAction::triggered, m_game_list_frame, &game_list_frame::SetShowCustomIcons);
|
||||||
connect(ui->playHoverGifsAct, &QAction::triggered, m_game_list_frame, &game_list_frame::SetPlayHoverGifs);
|
connect(ui->playHoverGifsAct, &QAction::triggered, m_game_list_frame, &game_list_frame::SetPlayHoverGifs);
|
||||||
|
|
||||||
connect(m_game_list_frame, &game_list_frame::RequestIconSizeChange, this, [this](const int& val)
|
connect(m_game_list_frame, &game_list_frame::RequestIconSizeChange, this, [this](int val)
|
||||||
{
|
{
|
||||||
const int idx = ui->sizeSlider->value() + val;
|
const int idx = ui->sizeSlider->value() + val;
|
||||||
m_save_slider_pos = true;
|
m_save_slider_pos = true;
|
||||||
|
|
|
||||||
|
|
@ -306,6 +306,7 @@
|
||||||
<addaction name="actionManage_Cheats"/>
|
<addaction name="actionManage_Cheats"/>
|
||||||
<addaction name="actionManage_Game_Patches"/>
|
<addaction name="actionManage_Game_Patches"/>
|
||||||
<addaction name="actionManage_Screenshots"/>
|
<addaction name="actionManage_Screenshots"/>
|
||||||
|
<addaction name="actionManage_SoundEffects"/>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QMenu" name="menuUtilities">
|
<widget class="QMenu" name="menuUtilities">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
|
|
@ -1442,6 +1443,11 @@
|
||||||
<string>Music Player</string>
|
<string>Music Player</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionManage_SoundEffects">
|
||||||
|
<property name="text">
|
||||||
|
<string>Sound Effects</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources>
|
<resources>
|
||||||
|
|
|
||||||
|
|
@ -432,9 +432,9 @@ memory_viewer_panel::memory_viewer_panel(QWidget* parent, std::shared_ptr<CPUDis
|
||||||
|
|
||||||
scroll(0); // Refresh
|
scroll(0); // Refresh
|
||||||
});
|
});
|
||||||
connect(sb_words, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, [=, this]()
|
connect(sb_words, &QSpinBox::valueChanged, this, [this](int value)
|
||||||
{
|
{
|
||||||
m_colcount = 1 << sb_words->value();
|
m_colcount = 1 << value;
|
||||||
ShowMemory();
|
ShowMemory();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -105,7 +105,7 @@ pad_motion_settings_dialog::pad_motion_settings_dialog(QDialog* parent, std::sha
|
||||||
m_config_entries[i]->mirrored.set(state != Qt::Unchecked);
|
m_config_entries[i]->mirrored.set(state != Qt::Unchecked);
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_shifts[i], QOverload<int>::of(&QSpinBox::valueChanged), this, [this, i](int value)
|
connect(m_shifts[i], &QSpinBox::valueChanged, this, [this, i](int value)
|
||||||
{
|
{
|
||||||
std::lock_guard lock(m_config_mutex);
|
std::lock_guard lock(m_config_mutex);
|
||||||
m_config_entries[i]->shift.set(value);
|
m_config_entries[i]->shift.set(value);
|
||||||
|
|
|
||||||
|
|
@ -123,8 +123,8 @@ patch_manager_dialog::patch_manager_dialog(std::shared_ptr<gui_settings> gui_set
|
||||||
handle_config_value_changed(ui->configurable_combo_box->itemData(index).toDouble());
|
handle_config_value_changed(ui->configurable_combo_box->itemData(index).toDouble());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
connect(ui->configurable_spin_box, QOverload<int>::of(&QSpinBox::valueChanged), this, &patch_manager_dialog::handle_config_value_changed);
|
connect(ui->configurable_spin_box, &QSpinBox::valueChanged, this, &patch_manager_dialog::handle_config_value_changed);
|
||||||
connect(ui->configurable_double_spin_box, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &patch_manager_dialog::handle_config_value_changed);
|
connect(ui->configurable_double_spin_box, &QDoubleSpinBox::valueChanged, this, &patch_manager_dialog::handle_config_value_changed);
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
|
connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QWidget::close);
|
||||||
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
|
connect(ui->buttonBox, &QDialogButtonBox::clicked, [this](QAbstractButton* button)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -281,7 +281,7 @@ void raw_mouse_settings_dialog::add_tabs(QTabWidget* tabs)
|
||||||
m_accel_spin_boxes.push_back(mouse_acceleration_spin_box);
|
m_accel_spin_boxes.push_back(mouse_acceleration_spin_box);
|
||||||
mouse_acceleration_spin_box->setRange(0.1, 10.0);
|
mouse_acceleration_spin_box->setRange(0.1, 10.0);
|
||||||
mouse_acceleration_spin_box->setValue(config->mouse_acceleration.get() / 100.0);
|
mouse_acceleration_spin_box->setValue(config->mouse_acceleration.get() / 100.0);
|
||||||
connect(mouse_acceleration_spin_box, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, [player](double value)
|
connect(mouse_acceleration_spin_box, &QDoubleSpinBox::valueChanged, this, [player](double value)
|
||||||
{
|
{
|
||||||
auto& config = ::at32(g_cfg_raw_mouse.players, player)->mouse_acceleration;
|
auto& config = ::at32(g_cfg_raw_mouse.players, player)->mouse_acceleration;
|
||||||
config.set(std::clamp(value * 100.0, config.min, config.max));
|
config.set(std::clamp(value * 100.0, config.min, config.max));
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@
|
||||||
|
|
||||||
LOG_CHANNEL(gui_log, "GUI");
|
LOG_CHANNEL(gui_log, "GUI");
|
||||||
|
|
||||||
enum SaveColumns
|
enum class SaveColumns
|
||||||
{
|
{
|
||||||
Icon = 0,
|
Icon = 0,
|
||||||
Name = 1,
|
Name = 1,
|
||||||
|
|
@ -60,30 +60,26 @@ save_manager_dialog::save_manager_dialog(std::shared_ptr<gui_settings> gui_setti
|
||||||
setMinimumSize(QSize(400, 400));
|
setMinimumSize(QSize(400, 400));
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
Init();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Future proofing. Makes it easier in future if I add ability to change directories
|
|
||||||
*/
|
|
||||||
void save_manager_dialog::Init()
|
|
||||||
{
|
|
||||||
// Table
|
// Table
|
||||||
m_list = new game_list();
|
m_list = new game_list();
|
||||||
m_list->setItemDelegate(new game_list_delegate(m_list));
|
m_list->setItemDelegate(new game_list_delegate(m_list));
|
||||||
m_list->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
m_list->setSelectionMode(QAbstractItemView::SelectionMode::ExtendedSelection);
|
||||||
m_list->setSelectionBehavior(QAbstractItemView::SelectRows);
|
m_list->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
m_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
m_list->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||||
m_list->setColumnCount(SaveColumns::Count);
|
m_list->setColumnCount(static_cast<int>(SaveColumns::Count));
|
||||||
m_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
m_list->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
m_list->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
m_list->setHorizontalScrollMode(QAbstractItemView::ScrollPerPixel);
|
||||||
m_list->verticalScrollBar()->setSingleStep(20);
|
m_list->verticalScrollBar()->setSingleStep(20);
|
||||||
m_list->horizontalScrollBar()->setSingleStep(10);
|
m_list->horizontalScrollBar()->setSingleStep(10);
|
||||||
m_list->setHorizontalHeaderLabels(QStringList() << tr("Icon") << tr("Title & Subtitle") << tr("Last Modified") << tr("Save ID") << tr("Notes"));
|
|
||||||
m_list->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
m_list->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Fixed);
|
||||||
m_list->horizontalHeader()->setStretchLastSection(true);
|
m_list->horizontalHeader()->setStretchLastSection(true);
|
||||||
m_list->setMouseTracking(true);
|
m_list->setMouseTracking(true);
|
||||||
|
|
||||||
|
for (int column = 0; column < static_cast<int>(SaveColumns::Count); column++)
|
||||||
|
{
|
||||||
|
m_list->setHorizontalHeaderItem(column, new QTableWidgetItem(get_header_text(column)));
|
||||||
|
}
|
||||||
|
|
||||||
// Bottom bar
|
// Bottom bar
|
||||||
const int icon_size = m_gui_settings->GetValue(gui::sd_icon_size).toInt();
|
const int icon_size = m_gui_settings->GetValue(gui::sd_icon_size).toInt();
|
||||||
m_icon_size = QSize(icon_size, icon_size * 176 / 320);
|
m_icon_size = QSize(icon_size, icon_size * 176 / 320);
|
||||||
|
|
@ -162,7 +158,7 @@ void save_manager_dialog::Init()
|
||||||
connect(m_button_folder, &QAbstractButton::clicked, [this]()
|
connect(m_button_folder, &QAbstractButton::clicked, [this]()
|
||||||
{
|
{
|
||||||
const int idx = m_list->currentRow();
|
const int idx = m_list->currentRow();
|
||||||
QTableWidgetItem* item = m_list->item(idx, SaveColumns::Name);
|
QTableWidgetItem* item = m_list->item(idx, static_cast<int>(SaveColumns::Name));
|
||||||
if (!item)
|
if (!item)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -176,12 +172,12 @@ void save_manager_dialog::Init()
|
||||||
connect(m_list, &QTableWidget::customContextMenuRequested, this, &save_manager_dialog::ShowContextMenu);
|
connect(m_list, &QTableWidget::customContextMenuRequested, this, &save_manager_dialog::ShowContextMenu);
|
||||||
connect(m_list, &QTableWidget::cellChanged, [&](int row, int col)
|
connect(m_list, &QTableWidget::cellChanged, [&](int row, int col)
|
||||||
{
|
{
|
||||||
if (col != SaveColumns::Note)
|
if (col != static_cast<int>(SaveColumns::Note))
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
QTableWidgetItem* user_item = m_list->item(row, SaveColumns::Name);
|
QTableWidgetItem* user_item = m_list->item(row, static_cast<int>(SaveColumns::Name));
|
||||||
QTableWidgetItem* text_item = m_list->item(row, SaveColumns::Note);
|
QTableWidgetItem* text_item = m_list->item(row, static_cast<int>(SaveColumns::Note));
|
||||||
if (!user_item || !text_item)
|
if (!user_item || !text_item)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -196,7 +192,7 @@ void save_manager_dialog::Init()
|
||||||
connect(m_list, &QTableWidget::itemSelectionChanged, this, &save_manager_dialog::UpdateDetails);
|
connect(m_list, &QTableWidget::itemSelectionChanged, this, &save_manager_dialog::UpdateDetails);
|
||||||
connect(this, &save_manager_dialog::IconReady, this, [this](int index, const QPixmap& pixmap)
|
connect(this, &save_manager_dialog::IconReady, this, [this](int index, const QPixmap& pixmap)
|
||||||
{
|
{
|
||||||
if (movie_item* item = static_cast<movie_item*>(m_list->item(index, SaveColumns::Icon)))
|
if (movie_item* item = static_cast<movie_item*>(m_list->item(index, static_cast<int>(SaveColumns::Icon))))
|
||||||
{
|
{
|
||||||
item->setData(SaveUserRole::PixmapScaled, pixmap);
|
item->setData(SaveUserRole::PixmapScaled, pixmap);
|
||||||
item->image_change_callback();
|
item->image_change_callback();
|
||||||
|
|
@ -205,6 +201,20 @@ void save_manager_dialog::Init()
|
||||||
connect(search_bar, &QLineEdit::textChanged, this, &save_manager_dialog::text_changed);
|
connect(search_bar, &QLineEdit::textChanged, this, &save_manager_dialog::text_changed);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString save_manager_dialog::get_header_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<SaveColumns>(col))
|
||||||
|
{
|
||||||
|
case SaveColumns::Icon: return tr("Icon");
|
||||||
|
case SaveColumns::Name: return tr("Title & Subtitle");
|
||||||
|
case SaveColumns::Time: return tr("Last Modified");
|
||||||
|
case SaveColumns::Dir: return tr("Save ID");
|
||||||
|
case SaveColumns::Note: return tr("Notes");
|
||||||
|
case SaveColumns::Count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This certainly isn't ideal for this code, as it essentially copies cellSaveData. But, I have no other choice without adding public methods to cellSaveData.
|
* This certainly isn't ideal for this code, as it essentially copies cellSaveData. But, I have no other choice without adding public methods to cellSaveData.
|
||||||
*/
|
*/
|
||||||
|
|
@ -300,6 +310,15 @@ void save_manager_dialog::UpdateList()
|
||||||
m_list->clearContents();
|
m_list->clearContents();
|
||||||
m_list->setRowCount(static_cast<int>(m_save_entries.size()));
|
m_list->setRowCount(static_cast<int>(m_save_entries.size()));
|
||||||
|
|
||||||
|
// Update headers
|
||||||
|
for (int col = 0; col < m_list->horizontalHeader()->count(); col++)
|
||||||
|
{
|
||||||
|
if (auto item = m_list->horizontalHeaderItem(col))
|
||||||
|
{
|
||||||
|
item->setText(get_header_text(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const QVariantMap notes = m_persistent_settings->GetValue(gui::persistent::save_notes).toMap();
|
const QVariantMap notes = m_persistent_settings->GetValue(gui::persistent::save_notes).toMap();
|
||||||
|
|
||||||
if (m_gui_settings->GetValue(gui::m_enableUIColors).toBool())
|
if (m_gui_settings->GetValue(gui::m_enableUIColors).toBool())
|
||||||
|
|
@ -358,20 +377,20 @@ void save_manager_dialog::UpdateList()
|
||||||
icon_item->stop_movie();
|
icon_item->stop_movie();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
m_list->setItem(i, SaveColumns::Icon, icon_item);
|
m_list->setItem(i, static_cast<int>(SaveColumns::Icon), icon_item);
|
||||||
|
|
||||||
custom_table_widget_item* titleItem = new custom_table_widget_item(title);
|
custom_table_widget_item* titleItem = new custom_table_widget_item(title);
|
||||||
titleItem->setData(Qt::UserRole, i); // For sorting to work properly
|
titleItem->setData(Qt::UserRole, i); // For sorting to work properly
|
||||||
titleItem->setFlags(titleItem->flags() & ~Qt::ItemIsEditable);
|
titleItem->setFlags(titleItem->flags() & ~Qt::ItemIsEditable);
|
||||||
m_list->setItem(i, SaveColumns::Name, titleItem);
|
m_list->setItem(i, static_cast<int>(SaveColumns::Name), titleItem);
|
||||||
|
|
||||||
custom_table_widget_item* timeItem = new custom_table_widget_item(gui::utils::format_timestamp(entry.mtime));
|
custom_table_widget_item* timeItem = new custom_table_widget_item(gui::utils::format_timestamp(entry.mtime));
|
||||||
timeItem->setFlags(timeItem->flags() & ~Qt::ItemIsEditable);
|
timeItem->setFlags(timeItem->flags() & ~Qt::ItemIsEditable);
|
||||||
m_list->setItem(i, SaveColumns::Time, timeItem);
|
m_list->setItem(i, static_cast<int>(SaveColumns::Time), timeItem);
|
||||||
|
|
||||||
custom_table_widget_item* dirNameItem = new custom_table_widget_item(dir_name);
|
custom_table_widget_item* dirNameItem = new custom_table_widget_item(dir_name);
|
||||||
dirNameItem->setFlags(dirNameItem->flags() & ~Qt::ItemIsEditable);
|
dirNameItem->setFlags(dirNameItem->flags() & ~Qt::ItemIsEditable);
|
||||||
m_list->setItem(i, SaveColumns::Dir, dirNameItem);
|
m_list->setItem(i, static_cast<int>(SaveColumns::Dir), dirNameItem);
|
||||||
|
|
||||||
custom_table_widget_item* noteItem = new custom_table_widget_item();
|
custom_table_widget_item* noteItem = new custom_table_widget_item();
|
||||||
noteItem->setFlags(noteItem->flags() | Qt::ItemIsEditable);
|
noteItem->setFlags(noteItem->flags() | Qt::ItemIsEditable);
|
||||||
|
|
@ -379,7 +398,7 @@ void save_manager_dialog::UpdateList()
|
||||||
{
|
{
|
||||||
noteItem->setText(notes[dir_name].toString());
|
noteItem->setText(notes[dir_name].toString());
|
||||||
}
|
}
|
||||||
m_list->setItem(i, SaveColumns::Note, noteItem);
|
m_list->setItem(i, static_cast<int>(SaveColumns::Note), noteItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_list->setSortingEnabled(true); // Enable sorting only after using setItem calls
|
m_list->setSortingEnabled(true); // Enable sorting only after using setItem calls
|
||||||
|
|
@ -422,7 +441,7 @@ void save_manager_dialog::UpdateIcons()
|
||||||
|
|
||||||
for (int i = 0; i < m_list->rowCount(); ++i)
|
for (int i = 0; i < m_list->rowCount(); ++i)
|
||||||
{
|
{
|
||||||
if (movie_item* icon_item = static_cast<movie_item*>(m_list->item(i, SaveColumns::Icon)))
|
if (movie_item* icon_item = static_cast<movie_item*>(m_list->item(i, static_cast<int>(SaveColumns::Icon))))
|
||||||
{
|
{
|
||||||
icon_item->setData(SaveUserRole::PixmapScaled, placeholder);
|
icon_item->setData(SaveUserRole::PixmapScaled, placeholder);
|
||||||
icon_item->setData(Qt::DecorationRole, placeholder);
|
icon_item->setData(Qt::DecorationRole, placeholder);
|
||||||
|
|
@ -430,14 +449,14 @@ void save_manager_dialog::UpdateIcons()
|
||||||
}
|
}
|
||||||
|
|
||||||
m_list->resizeRowsToContents();
|
m_list->resizeRowsToContents();
|
||||||
m_list->resizeColumnToContents(SaveColumns::Icon);
|
m_list->resizeColumnToContents(static_cast<int>(SaveColumns::Icon));
|
||||||
|
|
||||||
const s32 language_index = gui_application::get_language_id();
|
const s32 language_index = gui_application::get_language_id();
|
||||||
const std::string localized_icon = fmt::format("ICON0_%02d.PNG", language_index);
|
const std::string localized_icon = fmt::format("ICON0_%02d.PNG", language_index);
|
||||||
|
|
||||||
for (int i = 0; i < m_list->rowCount(); ++i)
|
for (int i = 0; i < m_list->rowCount(); ++i)
|
||||||
{
|
{
|
||||||
if (movie_item* icon_item = static_cast<movie_item*>(m_list->item(i, SaveColumns::Icon)))
|
if (movie_item* icon_item = static_cast<movie_item*>(m_list->item(i, static_cast<int>(SaveColumns::Icon))))
|
||||||
{
|
{
|
||||||
icon_item->set_icon_load_func([this, cancel = icon_item->icon_loading_aborted(), dpr, localized_icon](int index)
|
icon_item->set_icon_load_func([this, cancel = icon_item->icon_loading_aborted(), dpr, localized_icon](int index)
|
||||||
{
|
{
|
||||||
|
|
@ -448,12 +467,12 @@ void save_manager_dialog::UpdateIcons()
|
||||||
|
|
||||||
QPixmap icon;
|
QPixmap icon;
|
||||||
|
|
||||||
if (movie_item* item = static_cast<movie_item*>(m_list->item(index, SaveColumns::Icon)))
|
if (movie_item* item = static_cast<movie_item*>(m_list->item(index, static_cast<int>(SaveColumns::Icon))))
|
||||||
{
|
{
|
||||||
if (!item->data(SaveUserRole::PixmapLoaded).toBool())
|
if (!item->data(SaveUserRole::PixmapLoaded).toBool())
|
||||||
{
|
{
|
||||||
// Load game icon
|
// Load game icon
|
||||||
if (QTableWidgetItem* user_item = m_list->item(index, SaveColumns::Name))
|
if (QTableWidgetItem* user_item = m_list->item(index, static_cast<int>(SaveColumns::Name)))
|
||||||
{
|
{
|
||||||
const int idx_real = user_item->data(Qt::UserRole).toInt();
|
const int idx_real = user_item->data(Qt::UserRole).toInt();
|
||||||
const SaveDataEntry& entry = ::at32(m_save_entries, idx_real);
|
const SaveDataEntry& entry = ::at32(m_save_entries, idx_real);
|
||||||
|
|
@ -534,7 +553,7 @@ void save_manager_dialog::OnSort(int logicalIndex)
|
||||||
// Remove a save file, need to be confirmed.
|
// Remove a save file, need to be confirmed.
|
||||||
void save_manager_dialog::OnEntryRemove(int row, bool user_interaction)
|
void save_manager_dialog::OnEntryRemove(int row, bool user_interaction)
|
||||||
{
|
{
|
||||||
if (QTableWidgetItem* item = m_list->item(row, SaveColumns::Name))
|
if (QTableWidgetItem* item = m_list->item(row, static_cast<int>(SaveColumns::Name)))
|
||||||
{
|
{
|
||||||
const int idx_real = item->data(Qt::UserRole).toInt();
|
const int idx_real = item->data(Qt::UserRole).toInt();
|
||||||
const SaveDataEntry& entry = ::at32(m_save_entries, idx_real);
|
const SaveDataEntry& entry = ::at32(m_save_entries, idx_real);
|
||||||
|
|
@ -599,7 +618,7 @@ void save_manager_dialog::ShowContextMenu(const QPoint& pos)
|
||||||
connect(removeAct, &QAction::triggered, this, &save_manager_dialog::OnEntriesRemove); // entriesremove handles case of one as well
|
connect(removeAct, &QAction::triggered, this, &save_manager_dialog::OnEntriesRemove); // entriesremove handles case of one as well
|
||||||
connect(showDirAct, &QAction::triggered, [this, idx]()
|
connect(showDirAct, &QAction::triggered, [this, idx]()
|
||||||
{
|
{
|
||||||
QTableWidgetItem* item = m_list->item(idx, SaveColumns::Name);
|
QTableWidgetItem* item = m_list->item(idx, static_cast<int>(SaveColumns::Name));
|
||||||
if (!item)
|
if (!item)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
|
|
@ -655,8 +674,8 @@ void save_manager_dialog::UpdateDetails()
|
||||||
WaitForRepaintThreads(false);
|
WaitForRepaintThreads(false);
|
||||||
|
|
||||||
const int row = m_list->currentRow();
|
const int row = m_list->currentRow();
|
||||||
QTableWidgetItem* item = m_list->item(row, SaveColumns::Name);
|
QTableWidgetItem* item = m_list->item(row, static_cast<int>(SaveColumns::Name));
|
||||||
movie_item* icon_item = static_cast<movie_item*>(m_list->item(row, SaveColumns::Icon));
|
movie_item* icon_item = static_cast<movie_item*>(m_list->item(row, static_cast<int>(SaveColumns::Icon)));
|
||||||
|
|
||||||
if (!item || !icon_item)
|
if (!item || !icon_item)
|
||||||
{
|
{
|
||||||
|
|
@ -692,7 +711,7 @@ void save_manager_dialog::WaitForRepaintThreads(bool abort)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < m_list->rowCount(); i++)
|
for (int i = 0; i < m_list->rowCount(); i++)
|
||||||
{
|
{
|
||||||
if (movie_item* item = static_cast<movie_item*>(m_list->item(i, SaveColumns::Icon)))
|
if (movie_item* item = static_cast<movie_item*>(m_list->item(i, static_cast<int>(SaveColumns::Icon))))
|
||||||
{
|
{
|
||||||
item->wait_for_icon_loading(abort);
|
item->wait_for_icon_loading(abort);
|
||||||
}
|
}
|
||||||
|
|
@ -706,7 +725,7 @@ void save_manager_dialog::text_changed(const QString& text)
|
||||||
if (text.isEmpty())
|
if (text.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
for (int col = SaveColumns::Name; col < SaveColumns::Count; col++)
|
for (int col = static_cast<int>(SaveColumns::Name); col < static_cast<int>(SaveColumns::Count); col++)
|
||||||
{
|
{
|
||||||
const QTableWidgetItem* item = m_list->item(row, col);
|
const QTableWidgetItem* item = m_list->item(row, col);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,6 @@ Q_SIGNALS:
|
||||||
void IconReady(int index, const QPixmap& new_icon);
|
void IconReady(int index, const QPixmap& new_icon);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Init();
|
|
||||||
void UpdateList();
|
void UpdateList();
|
||||||
void UpdateIcons();
|
void UpdateIcons();
|
||||||
void ShowContextMenu(const QPoint& pos);
|
void ShowContextMenu(const QPoint& pos);
|
||||||
|
|
@ -49,6 +48,8 @@ private:
|
||||||
|
|
||||||
std::vector<SaveDataEntry> GetSaveEntries(const std::string& base_dir);
|
std::vector<SaveDataEntry> GetSaveEntries(const std::string& base_dir);
|
||||||
|
|
||||||
|
QString get_header_text(int col) const;
|
||||||
|
|
||||||
game_list* m_list = nullptr;
|
game_list* m_list = nullptr;
|
||||||
std::string m_dir;
|
std::string m_dir;
|
||||||
std::vector<SaveDataEntry> m_save_entries;
|
std::vector<SaveDataEntry> m_save_entries;
|
||||||
|
|
|
||||||
|
|
@ -63,15 +63,16 @@ savestate_manager_dialog::savestate_manager_dialog(std::shared_ptr<gui_settings>
|
||||||
m_game_table->setAlternatingRowColors(true);
|
m_game_table->setAlternatingRowColors(true);
|
||||||
m_game_table->installEventFilter(this);
|
m_game_table->installEventFilter(this);
|
||||||
|
|
||||||
auto add_game_column = [this](gui::savestate_game_list_columns col, const QString& header_text, const QString& action_text)
|
const auto add_game_column = [this](gui::savestate_game_list_columns col)
|
||||||
{
|
{
|
||||||
m_game_table->setHorizontalHeaderItem(static_cast<int>(col), new QTableWidgetItem(header_text));
|
const int column = static_cast<int>(col);
|
||||||
m_game_column_acts.append(new QAction(action_text, this));
|
m_game_table->setHorizontalHeaderItem(column, new QTableWidgetItem(get_gamelist_header_text(column)));
|
||||||
|
m_game_column_acts[column] = new QAction(get_gamelist_action_text(column), this);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_game_column(gui::savestate_game_list_columns::icon, tr("Icon"), tr("Show Icons"));
|
add_game_column(gui::savestate_game_list_columns::icon);
|
||||||
add_game_column(gui::savestate_game_list_columns::name, tr("Game"), tr("Show Games"));
|
add_game_column(gui::savestate_game_list_columns::name);
|
||||||
add_game_column(gui::savestate_game_list_columns::savestates, tr("Savestates"), tr("Show Savestates"));
|
add_game_column(gui::savestate_game_list_columns::savestates);
|
||||||
|
|
||||||
// Savestate Table
|
// Savestate Table
|
||||||
m_savestate_table = new game_list();
|
m_savestate_table = new game_list();
|
||||||
|
|
@ -94,16 +95,17 @@ savestate_manager_dialog::savestate_manager_dialog(std::shared_ptr<gui_settings>
|
||||||
m_savestate_table->setAlternatingRowColors(true);
|
m_savestate_table->setAlternatingRowColors(true);
|
||||||
m_savestate_table->installEventFilter(this);
|
m_savestate_table->installEventFilter(this);
|
||||||
|
|
||||||
auto add_savestate_column = [this](gui::savestate_list_columns col, const QString& header_text, const QString& action_text)
|
const auto add_savestate_column = [this](gui::savestate_list_columns col)
|
||||||
{
|
{
|
||||||
m_savestate_table->setHorizontalHeaderItem(static_cast<int>(col), new QTableWidgetItem(header_text));
|
const int column = static_cast<int>(col);
|
||||||
m_savestate_column_acts.append(new QAction(action_text, this));
|
m_savestate_table->setHorizontalHeaderItem(column, new QTableWidgetItem(get_savestate_header_text(column)));
|
||||||
|
m_savestate_column_acts[column] = new QAction(get_savestate_action_text(column), this);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_savestate_column(gui::savestate_list_columns::name, tr("Name"), tr("Show Names"));
|
add_savestate_column(gui::savestate_list_columns::name);
|
||||||
add_savestate_column(gui::savestate_list_columns::compatible, tr("Compatible"), tr("Show Compatible"));
|
add_savestate_column(gui::savestate_list_columns::compatible);
|
||||||
add_savestate_column(gui::savestate_list_columns::date, tr("Created"), tr("Show Created"));
|
add_savestate_column(gui::savestate_list_columns::date);
|
||||||
add_savestate_column(gui::savestate_list_columns::path, tr("Path"), tr("Show Paths"));
|
add_savestate_column(gui::savestate_list_columns::path);
|
||||||
|
|
||||||
m_splitter = new QSplitter();
|
m_splitter = new QSplitter();
|
||||||
m_splitter->addWidget(m_game_table);
|
m_splitter->addWidget(m_game_table);
|
||||||
|
|
@ -220,6 +222,56 @@ savestate_manager_dialog::~savestate_manager_dialog()
|
||||||
WaitAndAbortGameRepaintThreads();
|
WaitAndAbortGameRepaintThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString savestate_manager_dialog::get_savestate_header_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::savestate_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::savestate_list_columns::name: return tr("Name");
|
||||||
|
case gui::savestate_list_columns::compatible: return tr("Compatible");
|
||||||
|
case gui::savestate_list_columns::date: return tr("Created");
|
||||||
|
case gui::savestate_list_columns::path: return tr("Path");
|
||||||
|
case gui::savestate_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString savestate_manager_dialog::get_savestate_action_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::savestate_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::savestate_list_columns::name: return tr("Show Names");
|
||||||
|
case gui::savestate_list_columns::compatible: return tr("Show Compatible");
|
||||||
|
case gui::savestate_list_columns::date: return tr("Show Created");
|
||||||
|
case gui::savestate_list_columns::path: return tr("Show Paths");
|
||||||
|
case gui::savestate_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString savestate_manager_dialog::get_gamelist_header_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::savestate_game_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::savestate_game_list_columns::icon: return tr("Icon");
|
||||||
|
case gui::savestate_game_list_columns::name: return tr("Game");
|
||||||
|
case gui::savestate_game_list_columns::savestates: return tr("Savestates");
|
||||||
|
case gui::savestate_game_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString savestate_manager_dialog::get_gamelist_action_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::savestate_game_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::savestate_game_list_columns::icon: return tr("Show Icons");
|
||||||
|
case gui::savestate_game_list_columns::name: return tr("Show Games");
|
||||||
|
case gui::savestate_game_list_columns::savestates: return tr("Show Savestates");
|
||||||
|
case gui::savestate_game_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
bool savestate_manager_dialog::LoadSavestateFolderToDB(std::unique_ptr<game_savestates_data>&& game_savestates)
|
bool savestate_manager_dialog::LoadSavestateFolderToDB(std::unique_ptr<game_savestates_data>&& game_savestates)
|
||||||
{
|
{
|
||||||
ensure(!!game_savestates);
|
ensure(!!game_savestates);
|
||||||
|
|
@ -625,6 +677,21 @@ void savestate_manager_dialog::PopulateGameTable()
|
||||||
m_game_table->clearContents();
|
m_game_table->clearContents();
|
||||||
m_game_table->setRowCount(static_cast<int>(m_savestate_db.size()));
|
m_game_table->setRowCount(static_cast<int>(m_savestate_db.size()));
|
||||||
|
|
||||||
|
// Update headers
|
||||||
|
for (int col = 0; col < m_game_table->horizontalHeader()->count(); col++)
|
||||||
|
{
|
||||||
|
if (auto item = m_game_table->horizontalHeaderItem(col))
|
||||||
|
{
|
||||||
|
item->setText(get_gamelist_header_text(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update actions
|
||||||
|
for (auto& [col, action] : m_game_column_acts)
|
||||||
|
{
|
||||||
|
action->setText(get_gamelist_action_text(col));
|
||||||
|
}
|
||||||
|
|
||||||
m_game_combo->clear();
|
m_game_combo->clear();
|
||||||
m_game_combo->blockSignals(true);
|
m_game_combo->blockSignals(true);
|
||||||
|
|
||||||
|
|
@ -681,6 +748,21 @@ void savestate_manager_dialog::PopulateSavestateTable()
|
||||||
m_savestate_table->setRowCount(static_cast<int>(savestates.size()));
|
m_savestate_table->setRowCount(static_cast<int>(savestates.size()));
|
||||||
m_savestate_table->setSortingEnabled(false); // Disable sorting before using setItem calls
|
m_savestate_table->setSortingEnabled(false); // Disable sorting before using setItem calls
|
||||||
|
|
||||||
|
// Update headers
|
||||||
|
for (int col = 0; col < m_savestate_table->horizontalHeader()->count(); col++)
|
||||||
|
{
|
||||||
|
if (auto item = m_savestate_table->horizontalHeaderItem(col))
|
||||||
|
{
|
||||||
|
item->setText(get_savestate_header_text(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update actions
|
||||||
|
for (auto& [col, action] : m_savestate_column_acts)
|
||||||
|
{
|
||||||
|
action->setText(get_savestate_action_text(col));
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < static_cast<int>(savestates.size()); i++)
|
for (int i = 0; i < static_cast<int>(savestates.size()); i++)
|
||||||
{
|
{
|
||||||
const savestate_data& savestate = savestates[i];
|
const savestate_data& savestate = savestates[i];
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,12 @@ private:
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
bool eventFilter(QObject *object, QEvent *event) override;
|
bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
|
|
||||||
|
QString get_savestate_header_text(int col) const;
|
||||||
|
QString get_savestate_action_text(int col) const;
|
||||||
|
|
||||||
|
QString get_gamelist_header_text(int col) const;
|
||||||
|
QString get_gamelist_action_text(int col) const;
|
||||||
|
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
|
||||||
std::vector<game_info> m_game_info;
|
std::vector<game_info> m_game_info;
|
||||||
|
|
@ -74,8 +80,8 @@ private:
|
||||||
game_list* m_savestate_table; //! UI element to display savestate stuff.
|
game_list* m_savestate_table; //! UI element to display savestate stuff.
|
||||||
game_list* m_game_table; //! UI element to display games.
|
game_list* m_game_table; //! UI element to display games.
|
||||||
|
|
||||||
QList<QAction*> m_savestate_column_acts;
|
std::map<int, QAction*> m_savestate_column_acts;
|
||||||
QList<QAction*> m_game_column_acts;
|
std::map<int, QAction*> m_game_column_acts;
|
||||||
|
|
||||||
int m_game_icon_size_index = 25;
|
int m_game_icon_size_index = 25;
|
||||||
QSize m_game_icon_size = QSize(m_game_icon_size_index, m_game_icon_size_index);
|
QSize m_game_icon_size = QSize(m_game_icon_size_index, m_game_icon_size_index);
|
||||||
|
|
|
||||||
137
rpcs3/rpcs3qt/sound_effect_manager_dialog.cpp
Normal file
137
rpcs3/rpcs3qt/sound_effect_manager_dialog.cpp
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
#include "stdafx.h"
|
||||||
|
#include "sound_effect_manager_dialog.h"
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QScreen>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QMessageBox>
|
||||||
|
|
||||||
|
LOG_CHANNEL(gui_log, "GUI");
|
||||||
|
|
||||||
|
sound_effect_manager_dialog::sound_effect_manager_dialog(QWidget* parent)
|
||||||
|
: QDialog(parent)
|
||||||
|
{
|
||||||
|
setWindowTitle(tr("Sound Effects"));
|
||||||
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
|
|
||||||
|
QLabel* description = new QLabel(tr("You can import sound effects for the RPCS3 overlays here.\nThe file format is .wav and you should try to make the sounds as short as possible."), this);
|
||||||
|
|
||||||
|
QVBoxLayout* main_layout = new QVBoxLayout(this);
|
||||||
|
main_layout->addWidget(description);
|
||||||
|
|
||||||
|
const auto add_sound_widget = [this, main_layout](rsx::overlays::sound_effect sound)
|
||||||
|
{
|
||||||
|
ensure(!m_widgets.contains(sound));
|
||||||
|
|
||||||
|
QString name;
|
||||||
|
switch (sound)
|
||||||
|
{
|
||||||
|
case rsx::overlays::sound_effect::cursor: name = tr("Cursor"); break;
|
||||||
|
case rsx::overlays::sound_effect::accept: name = tr("Accept"); break;
|
||||||
|
case rsx::overlays::sound_effect::cancel: name = tr("Cancel"); break;
|
||||||
|
case rsx::overlays::sound_effect::osk_accept: name = tr("Onscreen keyboard accept"); break;
|
||||||
|
case rsx::overlays::sound_effect::osk_cancel: name = tr("Onscreen keyboard cancel"); break;
|
||||||
|
case rsx::overlays::sound_effect::dialog_ok: name = tr("Dialog popup"); break;
|
||||||
|
case rsx::overlays::sound_effect::dialog_error: name = tr("Error dialog popup"); break;
|
||||||
|
case rsx::overlays::sound_effect::trophy: name = tr("Trophy popup"); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPushButton* button = new QPushButton("", this);
|
||||||
|
connect(button, &QAbstractButton::clicked, this, [this, button, sound, name]()
|
||||||
|
{
|
||||||
|
const std::string path = rsx::overlays::get_sound_filepath(sound);
|
||||||
|
if (fs::is_file(path))
|
||||||
|
{
|
||||||
|
if (QMessageBox::question(this, tr("Remove sound effect?"), tr("Do you really want to remove the '%0' sound effect.").arg(name)) == QMessageBox::Yes)
|
||||||
|
{
|
||||||
|
if (!fs::remove_file(path))
|
||||||
|
{
|
||||||
|
gui_log.error("Failed to remove sound effect file '%s': %s", path, fs::g_tls_error);
|
||||||
|
}
|
||||||
|
|
||||||
|
update_widgets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const QString src_path = QFileDialog::getOpenFileName(this, tr("Select Audio File to Import"), "", tr("WAV (*.wav);;"));
|
||||||
|
if (!src_path.isEmpty())
|
||||||
|
{
|
||||||
|
if (!fs::copy_file(src_path.toStdString(), path, true))
|
||||||
|
{
|
||||||
|
gui_log.error("Failed to import sound effect file '%s' to '%s': %s", src_path, path, fs::g_tls_error);
|
||||||
|
}
|
||||||
|
update_widgets();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
QPushButton* play_button = new QPushButton(this);
|
||||||
|
play_button->setIcon(QApplication::style()->standardIcon(QStyle::SP_MediaPlay));
|
||||||
|
play_button->setIconSize(QSize(16, 16));
|
||||||
|
play_button->setFixedSize(24, 24);
|
||||||
|
connect(play_button, &QAbstractButton::clicked, this, [sound]()
|
||||||
|
{
|
||||||
|
rsx::overlays::play_sound(sound, 1.0f);
|
||||||
|
});
|
||||||
|
|
||||||
|
QHBoxLayout* layout = new QHBoxLayout(this);
|
||||||
|
layout->addWidget(button);
|
||||||
|
layout->addWidget(play_button);
|
||||||
|
layout->addStretch(1);
|
||||||
|
|
||||||
|
QGroupBox* gb = new QGroupBox(name, this);
|
||||||
|
gb->setLayout(layout);
|
||||||
|
|
||||||
|
main_layout->addWidget(gb);
|
||||||
|
|
||||||
|
m_widgets[sound] = {
|
||||||
|
.button = button,
|
||||||
|
.play_button = play_button
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::cursor);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::accept);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::cancel);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::osk_accept);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::osk_cancel);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::dialog_ok);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::dialog_error);
|
||||||
|
add_sound_widget(rsx::overlays::sound_effect::trophy);
|
||||||
|
|
||||||
|
setLayout(main_layout);
|
||||||
|
update_widgets();
|
||||||
|
resize(sizeHint());
|
||||||
|
}
|
||||||
|
|
||||||
|
sound_effect_manager_dialog::~sound_effect_manager_dialog()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void sound_effect_manager_dialog::update_widgets()
|
||||||
|
{
|
||||||
|
for (auto& [sound, widget] : m_widgets)
|
||||||
|
{
|
||||||
|
const bool file_exists = fs::is_file(rsx::overlays::get_sound_filepath(sound));
|
||||||
|
|
||||||
|
widget.play_button->setEnabled(file_exists);
|
||||||
|
|
||||||
|
if (file_exists)
|
||||||
|
{
|
||||||
|
widget.button->setText(tr("Remove"));
|
||||||
|
widget.button->setIcon(QApplication::style()->standardIcon(QStyle::SP_TrashIcon));
|
||||||
|
widget.button->setIconSize(QSize(16, 16));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
widget.button->setText(tr("Import"));
|
||||||
|
widget.button->setIcon(QApplication::style()->standardIcon(QStyle::SP_DialogOpenButton));
|
||||||
|
widget.button->setIconSize(QSize(16, 16));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
rpcs3/rpcs3qt/sound_effect_manager_dialog.h
Normal file
26
rpcs3/rpcs3qt/sound_effect_manager_dialog.h
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Emu/RSX/Overlays/overlays.h"
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
class sound_effect_manager_dialog : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit sound_effect_manager_dialog(QWidget* parent = nullptr);
|
||||||
|
~sound_effect_manager_dialog();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void update_widgets();
|
||||||
|
|
||||||
|
struct widget
|
||||||
|
{
|
||||||
|
QPushButton* button = nullptr;
|
||||||
|
QPushButton* play_button = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::map<rsx::overlays::sound_effect, widget> m_widgets;
|
||||||
|
};
|
||||||
|
|
@ -100,16 +100,17 @@ trophy_manager_dialog::trophy_manager_dialog(std::shared_ptr<gui_settings> gui_s
|
||||||
m_game_table->setAlternatingRowColors(true);
|
m_game_table->setAlternatingRowColors(true);
|
||||||
m_game_table->installEventFilter(this);
|
m_game_table->installEventFilter(this);
|
||||||
|
|
||||||
auto add_game_column = [this](gui::trophy_game_list_columns col, const QString& header_text, const QString& action_text)
|
const auto add_game_column = [this](gui::trophy_game_list_columns col)
|
||||||
{
|
{
|
||||||
m_game_table->setHorizontalHeaderItem(static_cast<int>(col), new QTableWidgetItem(header_text));
|
const int column = static_cast<int>(col);
|
||||||
m_game_column_acts.append(new QAction(action_text, this));
|
m_game_table->setHorizontalHeaderItem(column, new QTableWidgetItem(get_gamelist_header_text(column)));
|
||||||
|
m_game_column_acts[column] = new QAction(get_gamelist_action_text(column), this);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_game_column(gui::trophy_game_list_columns::icon, tr("Icon"), tr("Show Icons"));
|
add_game_column(gui::trophy_game_list_columns::icon);
|
||||||
add_game_column(gui::trophy_game_list_columns::name, tr("Game"), tr("Show Games"));
|
add_game_column(gui::trophy_game_list_columns::name);
|
||||||
add_game_column(gui::trophy_game_list_columns::progress, tr("Progress"), tr("Show Progress"));
|
add_game_column(gui::trophy_game_list_columns::progress);
|
||||||
add_game_column(gui::trophy_game_list_columns::trophies, tr("Trophies"), tr("Show Trophies"));
|
add_game_column(gui::trophy_game_list_columns::trophies);
|
||||||
|
|
||||||
// Trophy Table
|
// Trophy Table
|
||||||
m_trophy_table = new game_list();
|
m_trophy_table = new game_list();
|
||||||
|
|
@ -133,20 +134,21 @@ trophy_manager_dialog::trophy_manager_dialog(std::shared_ptr<gui_settings> gui_s
|
||||||
m_trophy_table->setAlternatingRowColors(true);
|
m_trophy_table->setAlternatingRowColors(true);
|
||||||
m_trophy_table->installEventFilter(this);
|
m_trophy_table->installEventFilter(this);
|
||||||
|
|
||||||
auto add_trophy_column = [this](gui::trophy_list_columns col, const QString& header_text, const QString& action_text)
|
const auto add_trophy_column = [this](gui::trophy_list_columns col)
|
||||||
{
|
{
|
||||||
m_trophy_table->setHorizontalHeaderItem(static_cast<int>(col), new QTableWidgetItem(header_text));
|
const int column = static_cast<int>(col);
|
||||||
m_trophy_column_acts.append(new QAction(action_text, this));
|
m_trophy_table->setHorizontalHeaderItem(column, new QTableWidgetItem(get_trophy_header_text(column)));
|
||||||
|
m_trophy_column_acts[column] = new QAction(get_trophy_action_text(column), this);
|
||||||
};
|
};
|
||||||
|
|
||||||
add_trophy_column(gui::trophy_list_columns::icon, tr("Icon"), tr("Show Icons"));
|
add_trophy_column(gui::trophy_list_columns::icon);
|
||||||
add_trophy_column(gui::trophy_list_columns::name, tr("Name"), tr("Show Names"));
|
add_trophy_column(gui::trophy_list_columns::name);
|
||||||
add_trophy_column(gui::trophy_list_columns::description, tr("Description"), tr("Show Descriptions"));
|
add_trophy_column(gui::trophy_list_columns::description);
|
||||||
add_trophy_column(gui::trophy_list_columns::type, tr("Type"), tr("Show Types"));
|
add_trophy_column(gui::trophy_list_columns::type);
|
||||||
add_trophy_column(gui::trophy_list_columns::is_unlocked, tr("Status"), tr("Show Status"));
|
add_trophy_column(gui::trophy_list_columns::is_unlocked);
|
||||||
add_trophy_column(gui::trophy_list_columns::id, tr("ID"), tr("Show IDs"));
|
add_trophy_column(gui::trophy_list_columns::id);
|
||||||
add_trophy_column(gui::trophy_list_columns::platinum_link, tr("Platinum Relevant"), tr("Show Platinum Relevant"));
|
add_trophy_column(gui::trophy_list_columns::platinum_link);
|
||||||
add_trophy_column(gui::trophy_list_columns::time_unlocked, tr("Time Unlocked"), tr("Show Time Unlocked"));
|
add_trophy_column(gui::trophy_list_columns::time_unlocked);
|
||||||
|
|
||||||
m_splitter = new QSplitter();
|
m_splitter = new QSplitter();
|
||||||
m_splitter->addWidget(m_game_table);
|
m_splitter->addWidget(m_game_table);
|
||||||
|
|
@ -406,6 +408,66 @@ trophy_manager_dialog::~trophy_manager_dialog()
|
||||||
WaitAndAbortTrophyRepaintThreads();
|
WaitAndAbortTrophyRepaintThreads();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString trophy_manager_dialog::get_trophy_header_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::trophy_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::trophy_list_columns::icon: return tr("Icon");
|
||||||
|
case gui::trophy_list_columns::name: return tr("Name");
|
||||||
|
case gui::trophy_list_columns::description: return tr("Description");
|
||||||
|
case gui::trophy_list_columns::type: return tr("Type");
|
||||||
|
case gui::trophy_list_columns::is_unlocked: return tr("Status");
|
||||||
|
case gui::trophy_list_columns::id: return tr("ID");
|
||||||
|
case gui::trophy_list_columns::platinum_link: return tr("Platinum Relevant");
|
||||||
|
case gui::trophy_list_columns::time_unlocked: return tr("Time Unlocked");
|
||||||
|
case gui::trophy_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString trophy_manager_dialog::get_trophy_action_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::trophy_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::trophy_list_columns::icon: return tr("Show Icons");
|
||||||
|
case gui::trophy_list_columns::name: return tr("Show Names");
|
||||||
|
case gui::trophy_list_columns::description: return tr("Show Descriptions");
|
||||||
|
case gui::trophy_list_columns::type: return tr("Show Types");
|
||||||
|
case gui::trophy_list_columns::is_unlocked: return tr("Show Status");
|
||||||
|
case gui::trophy_list_columns::id: return tr("Show IDs");
|
||||||
|
case gui::trophy_list_columns::platinum_link: return tr("Show Platinum Relevant");
|
||||||
|
case gui::trophy_list_columns::time_unlocked: return tr("Show Time Unlocked");
|
||||||
|
case gui::trophy_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString trophy_manager_dialog::get_gamelist_header_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::trophy_game_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::trophy_game_list_columns::icon: return tr("Icon");
|
||||||
|
case gui::trophy_game_list_columns::name: return tr("Game");
|
||||||
|
case gui::trophy_game_list_columns::progress: return tr("Progress");
|
||||||
|
case gui::trophy_game_list_columns::trophies: return tr("Trophies");
|
||||||
|
case gui::trophy_game_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString trophy_manager_dialog::get_gamelist_action_text(int col) const
|
||||||
|
{
|
||||||
|
switch (static_cast<gui::trophy_game_list_columns>(col))
|
||||||
|
{
|
||||||
|
case gui::trophy_game_list_columns::icon: return tr("Show Icons");
|
||||||
|
case gui::trophy_game_list_columns::name: return tr("Show Games");
|
||||||
|
case gui::trophy_game_list_columns::progress: return tr("Show Progress");
|
||||||
|
case gui::trophy_game_list_columns::trophies: return tr("Show Trophies");
|
||||||
|
case gui::trophy_game_list_columns::count: break;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
bool trophy_manager_dialog::LoadTrophyFolderToDB(const std::string& trop_name)
|
bool trophy_manager_dialog::LoadTrophyFolderToDB(const std::string& trop_name)
|
||||||
{
|
{
|
||||||
const std::string trophy_path = m_trophy_dir + trop_name;
|
const std::string trophy_path = m_trophy_dir + trop_name;
|
||||||
|
|
@ -1062,6 +1124,21 @@ void trophy_manager_dialog::PopulateGameTable()
|
||||||
m_game_table->clearContents();
|
m_game_table->clearContents();
|
||||||
m_game_table->setRowCount(static_cast<int>(m_trophies_db.size()));
|
m_game_table->setRowCount(static_cast<int>(m_trophies_db.size()));
|
||||||
|
|
||||||
|
// Update headers
|
||||||
|
for (int col = 0; col < m_game_table->horizontalHeader()->count(); col++)
|
||||||
|
{
|
||||||
|
if (auto item = m_game_table->horizontalHeaderItem(col))
|
||||||
|
{
|
||||||
|
item->setText(get_gamelist_header_text(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update actions
|
||||||
|
for (auto& [col, action] : m_game_column_acts)
|
||||||
|
{
|
||||||
|
action->setText(get_gamelist_action_text(col));
|
||||||
|
}
|
||||||
|
|
||||||
m_game_combo->clear();
|
m_game_combo->clear();
|
||||||
m_game_combo->blockSignals(true);
|
m_game_combo->blockSignals(true);
|
||||||
|
|
||||||
|
|
@ -1126,6 +1203,21 @@ void trophy_manager_dialog::PopulateTrophyTable()
|
||||||
m_trophy_table->setRowCount(all_trophies);
|
m_trophy_table->setRowCount(all_trophies);
|
||||||
m_trophy_table->setSortingEnabled(false); // Disable sorting before using setItem calls
|
m_trophy_table->setSortingEnabled(false); // Disable sorting before using setItem calls
|
||||||
|
|
||||||
|
// Update headers
|
||||||
|
for (int col = 0; col < m_trophy_table->horizontalHeader()->count(); col++)
|
||||||
|
{
|
||||||
|
if (auto item = m_trophy_table->horizontalHeaderItem(col))
|
||||||
|
{
|
||||||
|
item->setText(get_trophy_header_text(col));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update actions
|
||||||
|
for (auto& [col, action] : m_trophy_column_acts)
|
||||||
|
{
|
||||||
|
action->setText(get_trophy_action_text(col));
|
||||||
|
}
|
||||||
|
|
||||||
QPixmap placeholder(m_icon_height, m_icon_height);
|
QPixmap placeholder(m_icon_height, m_icon_height);
|
||||||
placeholder.fill(Qt::transparent);
|
placeholder.fill(Qt::transparent);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -83,6 +83,12 @@ private:
|
||||||
static QDateTime TickToDateTime(u64 tick);
|
static QDateTime TickToDateTime(u64 tick);
|
||||||
static u64 DateTimeToTick(QDateTime date_time);
|
static u64 DateTimeToTick(QDateTime date_time);
|
||||||
|
|
||||||
|
QString get_trophy_header_text(int col) const;
|
||||||
|
QString get_trophy_action_text(int col) const;
|
||||||
|
|
||||||
|
QString get_gamelist_header_text(int col) const;
|
||||||
|
QString get_gamelist_action_text(int col) const;
|
||||||
|
|
||||||
std::shared_ptr<gui_settings> m_gui_settings;
|
std::shared_ptr<gui_settings> m_gui_settings;
|
||||||
|
|
||||||
std::vector<std::unique_ptr<GameTrophiesData>> m_trophies_db; //! Holds all the trophy information.
|
std::vector<std::unique_ptr<GameTrophiesData>> m_trophies_db; //! Holds all the trophy information.
|
||||||
|
|
@ -93,8 +99,8 @@ private:
|
||||||
game_list* m_trophy_table; //! UI element to display trophy stuff.
|
game_list* m_trophy_table; //! UI element to display trophy stuff.
|
||||||
game_list* m_game_table; //! UI element to display games.
|
game_list* m_game_table; //! UI element to display games.
|
||||||
|
|
||||||
QList<QAction*> m_trophy_column_acts;
|
std::map<int, QAction*> m_trophy_column_acts;
|
||||||
QList<QAction*> m_game_column_acts;
|
std::map<int, QAction*> m_game_column_acts;
|
||||||
|
|
||||||
bool m_show_hidden_trophies = false;
|
bool m_show_hidden_trophies = false;
|
||||||
bool m_show_unlocked_trophies = true;
|
bool m_show_unlocked_trophies = true;
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ s32 trophy_notification_helper::ShowTrophyNotification(const SceNpTrophyDetails&
|
||||||
trophy_notification->move(m_game_window->mapToGlobal(QPoint(0, 0)));
|
trophy_notification->move(m_game_window->mapToGlobal(QPoint(0, 0)));
|
||||||
trophy_notification->show();
|
trophy_notification->show();
|
||||||
|
|
||||||
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_trophy.wav");
|
Emu.GetCallbacks().play_sound(fs::get_config_dir() + "sounds/snd_trophy.wav", std::nullopt);
|
||||||
});
|
});
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue