Compare commits

...

107 Commits

Author SHA1 Message Date
unexploredtest
6c6e19fdbe
Merge 6c98e7b538 into 5800b874d7 2025-06-10 22:44:52 +03:30
JMC47
5800b874d7
Merge pull request #13741 from Tilka/bean_menu
GameSettings: add bean menu patch for A Boy and His Blob
2025-06-09 00:12:52 -04:00
JMC47
1526c06133
Merge pull request #13658 from jordan-woyak/vk-present-done-race
Vulkan: Eliminate m_last_present_done flag.
2025-06-09 00:10:31 -04:00
JMC47
7ad85e875d
Merge pull request #13738 from Tilka/convert_banner
QtUtils/ImageConverter: simplify
2025-06-09 00:10:03 -04:00
JMC47
42d5f2b705
Merge pull request #13702 from CostPerUnit/master
MappingWidget: Add Advanced Configuration Button to Point And Point Passthrough "Enable" boxes
2025-06-09 00:09:35 -04:00
JMC47
5064b615ba
Merge pull request #13737 from LillyJadeKatrin/retroachievements-gamecube-bulk-fix
AchievementManager - Fix Gamecube Bulk Copy
2025-06-08 13:08:02 -04:00
JMC47
33b529a510
Merge pull request #13719 from LillyJadeKatrin/retroachievements-wii-menu-fix
AchievementManager - Block Wii Menu Exploits
2025-06-08 13:04:27 -04:00
JMC47
8c3ca46988
Merge pull request #13676 from LillyJadeKatrin/retroachievements-allowlist-test-improvements
RetroAchievements: Updated PatchAllowlistTest to generate new allowlist
2025-06-08 12:56:19 -04:00
Admiral H. Curtiss
944dd711b7
Merge pull request #13743 from JosJuice/audiocommon-missing-includes
AudioCommon: Re-add missing includes
2025-06-08 13:41:41 +02:00
JosJuice
1b7d42f775 AudioCommon: Re-add missing includes
7c237bb ("AudioCommon: Remove unused includes") removed some includes
that were in fact in use.
2025-06-08 11:35:02 +02:00
JMC47
24b0bf01d5
Merge pull request #12836 from JosJuice/opensles-buffer-size
Android: Ask system for optimal audio buffer size and sample rate
2025-06-07 23:07:37 -04:00
Tilka
19fbbf0dba
Merge pull request #13727 from JoshuaVandaele/fmt-11.2.0-localtime-deprec
fmt: Replace deprecated `fmt::localtime` usage with `Common::LocalTime`
2025-06-08 04:04:37 +01:00
Jordan Woyak
1786e34bd3
Merge pull request #13665 from jordan-woyak/dark-mode-filter
DolphinQt: Replace widespread SetQWidgetWindowDecorations calls with an event filter.
2025-06-07 18:19:13 -05:00
Jordan Woyak
65f3ba70f5
Merge pull request #13522 from tygyh/Enforce-overriding-destructor-style-Core&UnitTests
Core & UnitTests: Make overriding explicit and remove redundant virtual specifiers on overriding destructors
2025-06-07 17:55:14 -05:00
Jordan Woyak
ec52a74967
Merge pull request #13023 from tygyh/Replace-ties-with-structured-bindings
UnitTests: Replace ties with structured bindings
2025-06-07 17:50:34 -05:00
Jordan Woyak
8b7669550f
Merge pull request #13454 from tygyh/Use-constants-DolphinQt-FifoAnalyzer
DolphinQt/FIFO/FIFOAnalyzer: Make parameters, arguments etc. constant
2025-06-07 17:50:08 -05:00
Jordan Woyak
46e66fe945
Merge pull request #13544 from tygyh/DolphinNoGUI-Replace-deprecated-signal-header
DolphinNoGUI: Apply style-alignment refactorings
2025-06-07 17:47:11 -05:00
Jordan Woyak
056ece6f29
Merge pull request #13697 from tygyh/AudioCommon/Remove-unused-includes
AudioCommon: Remove unused includes
2025-06-07 17:45:50 -05:00
Jordan Woyak
a07a2fe398
Merge pull request #13698 from tygyh/AudioCommon/Remove-unused-qualifiers-and-make-variables-constant
AudioCommon: Remove unused qualifiers and make variables constant
2025-06-07 17:45:33 -05:00
Tillmann Karras
61e8fa060b QtUtils/ImageConverter: simplify 2025-06-07 23:06:07 +01:00
Tillmann Karras
b6ff1b5573 GameSettings: add bean menu patch for A Boy and His Blob
The bean menu in this game does not react when the analog control stick
is moved perfectly to the right (0 degress). This happens when the
analog stick is mapped to digital inputs.

Currently, Dolphin contains a hardcoded controller hack to work around
this issue. With this patch, it should no longer be needed; see #13177.
2025-06-07 23:01:17 +01:00
Jordan Woyak
5906512847 DolphinQt: Replace widespread SetQWidgetWindowDecorations calls with an event filter. 2025-06-07 16:15:34 -05:00
JMC47
52fcdde485
Merge pull request #13386 from iwubcode/resource_manager_system
VideoCommon: add resource manager, tracks resources to load assets in optimal way and manage memory
2025-06-07 15:51:34 -04:00
JMC47
5eb61024c6
Merge pull request #13740 from JoshuaVandaele/bsod-fix-i-hope
Host: Clean up device handle in all cases
2025-06-07 12:27:49 -04:00
Admiral H. Curtiss
a27b845514
Merge pull request #13710 from TryTwo/UI_Sliders_Update
Advanced Panel convert QSliders into ConfigSliders
2025-06-07 17:39:40 +02:00
Admiral H. Curtiss
1b1ca019a4
Merge pull request #13724 from SuperSamus/gamelist-properties-noduplicates
GameList: Prevent opening Properties multiple times for the same game
2025-06-07 17:24:50 +02:00
Joshua Vandaële
241834709b
Host: Clean up device handle 2025-06-07 16:55:45 +02:00
LillyJadeKatrin
c68549e9ef AchievementManager - Load unknown games
Prior to this change, any game unrecognized by RetroAchievements would ultimately result in the game being "Closed" by AchievementManager. As a result, if any game was run while in this state without any other closing being done, AchievementManager would simply load it like a new game, despite memory already being accessed.
However, testing and documentation determined that the rcheevos client doesn't actually complain when it fails to hash a game; it just runs this as "Unidentified Game" with RA ID = 0. As such, this change utilizes that in AchievementManager to differentiate between no software running and unidentified software running.

As a result of this, now LoadGame needs to be called for every piece of runnable software, supported format or otherwise. If a supported format is not available, LoadGame can now be called with a nullptr to ensure that rcheevos still properly sets up an unidentified game.
2025-06-07 07:02:24 -04:00
LillyJadeKatrin
5545a386cf AchievementManager - Fix Gamecube Bulk Copy
The memory copy algorithm (only needed for RetroAchievements devs) was broken for Gamecube as it assumed EXRAM size was zero when in reality it's using ARAM. For the time being, we do not need to use or access ARAM so instead this sets that value to zero for Gamecube titles.
2025-06-07 07:00:47 -04:00
JosJuice
185b080f03
Merge pull request #13142 from JosJuice/fifo-window-starting-stopping
DolphinQt: Call FIFOPlayerWindow::UpdateControls for Starting/Stopping
2025-06-07 10:43:19 +02:00
iwubcode
c3d3b81533 VideoCommon: remove 'GetByteSizeInMemory()' from custom asset, it is not needed anymore 2025-06-06 23:03:02 -05:00
iwubcode
774a84a953 VideoCommon: avoid race conditions with asset load/unload by moving the lock to the entire function, favor atomics for the memory/time getters 2025-06-06 23:03:02 -05:00
iwubcode
b3f50c969e VideoCommon: rename m_bytes_loaded in asset library to bytes_loaded 2025-06-06 23:03:02 -05:00
iwubcode
3b83907b88 VideoCommon: update CustomAsset's load time to be before the load occurs (this prevents issues where the load time might be incorrectly inflated by long load operations)
Co-authored-by: Jordan Woyak <jordan.woyak@gmail.com>
2025-06-06 23:03:02 -05:00
iwubcode
d940d62cae VideoCommon: watch texture pack folder for texture reloads (from dynamic input textures) 2025-06-06 23:03:02 -05:00
iwubcode
7afa9e6c6f VideoCommon: use CustomResourceManager in the texture cache and hook up to our hires textures 2025-06-06 23:03:02 -05:00
iwubcode
12d178a8df VideoCommon: initialize and shutdown the CustomResourceManager when the video thread initializes and shuts down 2025-06-06 23:03:02 -05:00
iwubcode
f910c1d934 Core: add CustomResourceManager to System 2025-06-06 23:03:02 -05:00
iwubcode
70abcb2030 VideoCommon: add resource manager and new asset loader; the resource manager uses a least recently used cache to determine which assets get priority for loading. Additionally, if the system is low on memory, assets will be purged with the less requested assets being the first to go. The loader is multithreaded now and loads assets as quickly as possible as long as memory is available
Co-authored-by: Jordan Woyak <jordan.woyak@gmail.com>
2025-06-06 23:03:02 -05:00
iwubcode
d8ea31ca46 VideoCommon: rename GameTextureAsset into TextureAsset and make it only contain CustomTextureData. Move validation and load logic to individual functions 2025-06-06 23:03:02 -05:00
iwubcode
2ae43324cb VideoCommon: move AssetMap to a types header file, so it can be pulled in without the DirectFilesystemAssetLibrary dependencies, the header will be expanded later 2025-06-06 23:03:02 -05:00
iwubcode
7d59c2743d Common: Add class 'FilesystemWatcher' that is used to watch paths and receive callbacks about filesystem level events for anything under that path 2025-06-06 23:03:02 -05:00
iwubcode
8113399b68 Externals: add watcher, a library used to watch a filesystem location for changes 2025-06-06 23:03:02 -05:00
iwubcode
bafe78203d VideoCommon: remove 'GetLastAssetWriteTime' and switch to a steady_clock for asset times 2025-06-06 23:03:02 -05:00
iwubcode
15f125ebee VideoCommon: change asset loading to return the number of bytes loaded instead of a pass/fail 2025-06-06 23:03:02 -05:00
iwubcode
316740daed VideoCommon: add 'Unload' functionality to CustomAsset 2025-06-06 23:03:02 -05:00
Jordan Woyak
903eafcf65
Merge pull request #13714 from Dentomologist/dolphinqt_remove_redundant_window_hints
DolphinQt: Remove redundant window hints
2025-06-06 22:13:01 -05:00
Dentomologist
2a7e8a4003 DolphinQt: Remove redundant window hints
Remove window hints clearing the flag Qt::WindowContextHelpButtonHint,
which is already off by default in Qt 6.

In Qt 5 this flag was set by default for QDialogs, and on Windows put a
? button in the corner of the title bar allowing users to activate Qt's
QWhatsThis help system for a given widget. Since we don't set that text
the ? button was useless and so we hid it manually.
2025-06-06 19:35:13 -07:00
iwubcode
9ec69b5925 VideoCommon: add a handle to custom asset, this is an id that is only relevant for a particular game session but is slightly faster as a numeric value for lookups than the traditional asset id 2025-06-06 19:20:25 -05:00
iwubcode
d7de49ccf6 Core / VideoCommon: Remove original custom asset loader 2025-06-06 19:20:25 -05:00
JMC47
5ec5db9240
Merge pull request #13392 from jordan-woyak/frame-pacing-accurate-time
CoreTiming: Add setting to pursue accurate overall emulation runtime
2025-06-06 19:17:44 -04:00
JMC47
974c56d3c5
Merge pull request #13731 from iwubcode/pixel_shader_gen_fix_complete_initialize
VideoCommon: ensure pixel shader gen input structure is completely initialized
2025-06-06 19:08:57 -04:00
Jordan Woyak
977f2da6a7
Merge pull request #13735 from JMC47/triopatch
GamePatch: Disney Trio of Destruction Pagetable Speedhack.
2025-06-06 17:54:36 -05:00
JMC47
b1d114f7f7
Merge pull request #13730 from jordan-woyak/controllers-on-main-config-dialog
DolphinQt: Move "Controllers" to main settings window.
2025-06-06 18:54:12 -04:00
JMC47
be3d48ec5f GamePatch: Disney Trio of Destruction Pagetable Speedhack. 2025-06-06 17:17:11 -04:00
Jordan Woyak
a0611b512b
Merge pull request #13713 from Dentomologist/filesystemwidget_center_header_text
FilesystemWidget: Center header text
2025-06-05 14:34:36 -05:00
JMC47
fadc2ac223
Merge pull request #13732 from AdmiralCurtiss/dsp-jit-exceptions
DSP LLE Recompiler: Fix exception handling after #10766
2025-06-05 15:17:30 -04:00
Admiral H. Curtiss
ea959f2651
DSP/Jit: Don't return to dispatcher if no exception was generated 2025-06-05 20:57:27 +02:00
Admiral H. Curtiss
a43fc68452
DSPAnalyzer: Set store instructions as potentially generating exceptions 2025-06-05 19:10:42 +02:00
iwubcode
ae26b38fc0 VideoCommon: fix pixel shader gen error about structure not being fully initialized 2025-06-05 01:37:45 -05:00
Jordan Woyak
b9bea58f0f DolphinQt: Move "Controllers" to main settings window. 2025-06-04 19:33:01 -05:00
JosJuice
b7fb2fa737
Merge pull request #13728 from JosJuice/android-uses-microphone
Android: Add android.hardware.microphone to manifest
2025-06-04 23:37:17 +02:00
Martino Fontana
2de9122b5f GameList: Prevent opening Properties multiple times for the same game 2025-06-04 23:11:09 +02:00
JMC47
8665b22822
Merge pull request #13651 from jordan-woyak/config-list
DolphinQt: Change Config QTabWidget into a QListWidget and QStackedWidget.
2025-06-04 16:01:51 -04:00
Dr. Dystopia
bae0e5f67a DolphinNoGUI: Make override explicit 2025-06-04 21:49:29 +02:00
Dr. Dystopia
2ae928ca79 DolphinNoGUI: Make parameters constant 2025-06-04 21:49:15 +02:00
Dr. Dystopia
f04f659710 DolphinNoGUI: Replace C-style cast with reinterpret_cast 2025-06-04 21:49:01 +02:00
Dr. Dystopia
ec1d659363 DolphinNoGUI: Make classes final 2025-06-04 21:48:53 +02:00
Dr. Dystopia
c37933932d DolphinNoGUI: Make variables constant 2025-06-04 21:48:40 +02:00
Dr. Dystopia
23af1e025b DolphinNoGUI: Make function static 2025-06-04 21:30:59 +02:00
Dr. Dystopia
135b6840e5 DolphinNoGUI: Remove unused include directives 2025-06-04 21:30:59 +02:00
Dr. Dystopia
e3df00b7f4 DolphinNoGUI: Make variables constexpr 2025-06-04 21:30:59 +02:00
Dr. Dystopia
71da0f2d24 DolphinNoGUI: Replace deprecated signal.h header 2025-06-04 21:30:59 +02:00
JosJuice
5d2518d490 Android: Add android.hardware.microphone to manifest
Google Play is now blocking distribution for Android TV unless we
explicitly set the android.hardware.microphone hardware feature as
android:required="false", because it's inferring
android.hardware.microphone from the android.permission.RECORD_AUDIO we
added for Wii Speak emulation, with android:required defaulting to true.
I was under the belief that setting android:required="false" on
android.permission.RECORD_AUDIO would solve this, but looking closer at
the definition of <uses-permission>, it doesn't actually support
android:required attributes, so that presumably has no effect.
2025-06-04 21:30:51 +02:00
JMC47
3f090dd474
Merge pull request #13681 from iwubcode/material_overhaul_custom_vertex
VideoCommon: move vertex shader gen logic to a 'process_vertex()' for use in future custom shaders
2025-06-04 15:27:47 -04:00
JMC47
8def02072b
Merge pull request #13379 from JoshuaVandaele/system-ng
Use minizip-ng in non-compatibility mode
2025-06-04 15:21:05 -04:00
JMC47
84f2af73e6
Merge pull request #13649 from SuperSamus/scooby-doo-night-of-100-texture-caches
GameINI: Set texture cache accuracy for Scooby-Doo! Night of 100 Frights PAL
2025-06-04 15:17:10 -04:00
Joshua Vandaële
4b65cc9a4c
fmt: Replace deprecated fmt::localtime usage with Common::LocalTime 2025-06-04 13:32:12 +02:00
Dr. Dystopia
8192d9d2a9 Make parameters, arguments etc. constant 2025-05-31 20:57:54 +02:00
Dr. Dystopia
a6b04f53e0 AudioCommon: Remove unused qualifiers and make variables constant 2025-05-30 21:48:38 +02:00
Jordan Woyak
a8eafa4ccd DolphinQt: Move the "Point (Passthrough)" "Enabled" checkbox below the mapping indicator. 2025-05-29 19:46:53 -05:00
CostPerUnit
a5b4a0b9e4 InputCommon/DolphinQt: Add advanced settings button for "Point" and "Point (Passthrough)" "Enabled" checkboxes. 2025-05-29 19:39:10 -05:00
LillyJadeKatrin
fd285f6348 AchievementManager - Minor cleanup
Deleting the unused m_game_data and m_is_game_loaded fields.
2025-05-29 18:35:30 -04:00
Dentomologist
3dc1605569 FilesystemWidget: Center header text
Center header text to match all the other headers.
2025-05-27 12:34:20 -07:00
TryTwo
a6a5e201b6 Qt Advanced Panel: Convert QSliders into ConfigSliders.
Part of the refactor into the config system.
2025-05-26 19:52:30 -07:00
Jordan Woyak
aafe961177 DolphinQt: Make GeckoCodeWidget default size not taller than it needs to be. 2025-05-26 20:58:48 -05:00
Jordan Woyak
eed7843d4a DolphinQt: Add stretch to the end of the game config Info tab. 2025-05-26 20:58:48 -05:00
Jordan Woyak
1e4dfc0956 DolphinQt: Fix the WiiPane hinting a larger than required size. 2025-05-26 20:58:48 -05:00
Jordan Woyak
5bc661aeca DolphinQt/AudioPane: Fix Volume QGroupBox title uglyness on Windows and inconsistent percent-sign spacing. 2025-05-26 20:58:48 -05:00
Jordan Woyak
fcff7a3a49 DolphinQt: Fix FilesystemWidget QTreeView visual style. 2025-05-26 20:58:48 -05:00
Jordan Woyak
543b85a451 DolphinQt: Make WrapInScrollArea and GetWrappedWidget less hacky. 2025-05-26 20:58:48 -05:00
Jordan Woyak
e796e82e8c DolphinQt: Change game properties QTabWidget to QListWidget. 2025-05-26 20:58:48 -05:00
Jordan Woyak
2b9935e6f4 DolphinQt: Change main settings window QTabWidget into a QListWidget and QStackedWidget. 2025-05-26 20:58:48 -05:00
unexploredtest
6c98e7b538 Move glslang target_include_directories back to glslang's CMakeLists.txt 2025-05-26 22:38:32 +03:30
JosJuice
f99d3dbd5c Android: Ask system for optimal audio buffer size and sample rate
This can reduce audio latency according to
https://developer.android.com/ndk/guides/audio/opensl/opensl-prog-notes#perform.

Previously we were using the hardcoded values of 48000 Hz and 256 frames
per buffer. The sample rate we use with this change is 48000 Hz on all
devices I'm aware of, but the buffer size does vary across devices.

Terminology note: The old code used the term "sample" to refer to what
Android refers to as a "frame". "Frame" is a clearer term to use for
this, so I've changed OpenSLESStream's terminology. One frame consists
of one sample per channel.
2025-05-25 11:59:33 +02:00
JosJuice
34e8fb068f Android: Get rid of OpenSLESStream's global state
Not sure if we're ever going to want to have more than one of these at
the same time, but these global variables are a code smell nonetheless.

I'm also deleting the existing member variables because they were
unused.
2025-05-25 11:55:22 +02:00
Dr. Dystopia
7c237bbd7c AudioCommon: Remove unused includes 2025-05-25 10:30:41 +02:00
iwubcode
b23dddea4e VideoCommon: move vertex shader gen logic to a 'process_vertex()' function, to eventually allow for custom shaders to override vertex logic 2025-05-24 01:27:58 -05:00
unexploredtest
b61a398e18 Use CMAKE_CURRENT_SOURCE_DIR instead of CMAKE_SOURCE_DIR 2025-05-23 23:42:32 +03:30
Joshua Vandaële
2ed5f16600
minizip-ng: Stop using compatibility mode 2025-05-22 12:51:55 +02:00
LillyJadeKatrin
c23b4e1020 RetroAchievements: Updated PatchAllowlistTest to generate new allowlist
Refactors the PatchAllowlistTest to streamline the experience for developers. Instead of a textual description of what needs to change in ApprovedInis.json for RetroAchievements compatibility, the test will now generate a replacement file and instruct the coder where to copy it in their local branch, and what to update APPROVED_LIST_HASH to. The result should be easier and more instructive for developers to make changes, while still maintaining that allowed codes cannot be added or modified without recompiling Dolphin.

As ApprovedInis.json no longer needs to be user-readable for this process, it no longer contains titles or pretty formatting and as such is updated in this commit, hash included.
2025-05-21 21:38:34 -04:00
Martino Fontana
8b228503d9 GameINI: Set texture cache accuracy for Scooby-Doo! Night of 100 Frights PAL 2025-05-17 13:35:17 +02:00
Jordan Woyak
1554e4ab6c Vulkan: Eliminate m_last_present_done flag. 2025-05-13 20:13:18 -05:00
Jordan Woyak
ec29d120b5 CoreTiming: Add a setting to pursue accurate emulation time. 2025-05-02 15:23:43 -05:00
Dr. Dystopia
f240e20e3f Make overriding explicit and remove redundant virtual specifiers on overriding destructors - Core & UnitTests 2025-05-01 15:00:37 +02:00
JosJuice
d48e6e25ad DolphinQt: Call FIFOPlayerWindow::UpdateControls for Starting/Stopping
Follow-up for
https://github.com/dolphin-emu/dolphin/pull/12918#discussion_r1785153070.
2024-10-20 13:38:24 +02:00
Dr. Dystopia
096ab8c026 Replace ties with structured bindings - UnitTests 2024-08-20 15:09:44 +02:00
364 changed files with 3265 additions and 3447 deletions

3
.gitmodules vendored
View File

@ -84,6 +84,9 @@
[submodule "Externals/Vulkan-Headers"]
path = Externals/Vulkan-Headers
url = https://github.com/KhronosGroup/Vulkan-Headers.git
[submodule "Externals/watcher/watcher"]
path = Externals/watcher/watcher
url = https://github.com/e-dant/watcher.git
[submodule "Externals/SFML/SFML"]
path = Externals/SFML/SFML
url = https://github.com/SFML/SFML.git

View File

@ -691,8 +691,8 @@ dolphin_find_optional_system_library_pkgconfig(ZSTD libzstd>=1.4.0 zstd::zstd Ex
dolphin_find_optional_system_library_pkgconfig(ZLIB zlib>=1.3.1 ZLIB::ZLIB Externals/zlib-ng)
dolphin_find_optional_system_library_pkgconfig(MINIZIP
"minizip>=4.0.4" minizip::minizip Externals/minizip-ng
dolphin_find_optional_system_library_pkgconfig(minizip-ng
"minizip-ng>=4.0.4" minizip-ng::minizip-ng Externals/minizip-ng
)
dolphin_find_optional_system_library(LZO Externals/LZO)
@ -784,6 +784,8 @@ if (USE_RETRO_ACHIEVEMENTS)
add_subdirectory(Externals/rcheevos)
endif()
add_subdirectory(Externals/watcher)
########################################
# Pre-build events: Define configuration variables and write SCM info header
#

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,5 @@
# GIHP78 - Scooby-Doo! Night of 100 Frights
[Video_Settings]
# Fixes video stuttering on FMVs encoded at 25 FPS
SafeTextureCacheColorSamples = 512

View File

@ -0,0 +1,8 @@
# SBLE5G - A Boy and His Blob
[OnFrame]
$Fix selecting right-most bean
0x800BD308:dword:0x4181000C
[OnFrame_Enabled]
$Fix selecting right-most bean

View File

@ -0,0 +1,8 @@
# SBLP5G - A Boy and His Blob
[OnFrame]
$Fix selecting right-most bean
0x800BE268:dword:0x4181000C
[OnFrame_Enabled]
$Fix selecting right-most bean

View File

@ -0,0 +1,9 @@
# SCYE4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019CB1C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYP4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019CB1C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYR4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019B4EC:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYX4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019CBBC:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYY4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019B55C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SCYZ4Q - Cars 2
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8019B55C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -1,4 +1,4 @@
# SQIE4Q, SQIP4Q - Disney Infinity
# SQIE4Q, SQIP4Q, SQIY4Q - Disney Infinity
[Core]
# Values set here will override the main Dolphin settings.

View File

@ -0,0 +1,9 @@
# SQIE4Q - Disney Infinity
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8008E60C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SQIP4Q - Disney Infinity
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8008E60C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# SQIY4Q - Disney Infinity
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x8008E60C:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSE4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSP4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSP4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA354:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSX4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA354:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSY4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSY4Q - Toy Story 3
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA354:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -0,0 +1,9 @@
# STSZ4Q - Toy Story 3 Toy Box Special Edition
[OnFrame]
#This speedhack modifies the way the game manages memory to run faster in Dolphin.
$BAT Speedhack
0x801FA2E4:dword:0x48000180
[OnFrame_Enabled]
$BAT Speedhack

View File

@ -77,5 +77,5 @@ dolphin_disable_warnings(glslang)
target_include_directories(glslang
PRIVATE
${CMAKE_SOURCE_DIR}/Externals/glslang
${CMAKE_CURRENT_SOURCE_DIR}
)

View File

@ -6,10 +6,10 @@ include(CheckIncludeFile)
add_library(minizip STATIC
minizip-ng/mz.h
# minizip-ng/compat/crypt.h
minizip-ng/compat/ioapi.c
minizip-ng/compat/ioapi.h
minizip-ng/compat/unzip.c
minizip-ng/compat/unzip.h
# minizip-ng/compat/ioapi.c
# minizip-ng/compat/ioapi.h
# minizip-ng/compat/unzip.c
# minizip-ng/compat/unzip.h
# minizip-ng/compat/zip.c
# minizip-ng/compat/zip.h
minizip-ng/mz_crypt.c
@ -93,4 +93,4 @@ endif()
target_link_libraries(minizip PUBLIC ZLIB::ZLIB)
add_library(minizip::minizip ALIAS minizip)
add_library(minizip-ng::minizip-ng ALIAS minizip)

View File

@ -23,8 +23,6 @@
</ClCompile>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="minizip-ng\compat\ioapi.c" />
<ClCompile Include="minizip-ng\compat\unzip.c" />
<ClCompile Include="minizip-ng\mz_crypt.c" />
<ClCompile Include="minizip-ng\mz_os.c" />
<ClCompile Include="minizip-ng\mz_os_win32.c" />
@ -39,8 +37,6 @@
</ItemGroup>
<ItemGroup>
<ClInclude Include="minizip-ng\mz.h" />
<ClCompile Include="minizip-ng\compat\ioapi.h" />
<ClCompile Include="minizip-ng\compat\unzip.h" />
<ClInclude Include="minizip-ng\mz_crypt.h" />
<ClInclude Include="minizip-ng\mz_os.h" />
<ClInclude Include="minizip-ng\mz_strm.h" />

4
Externals/watcher/CMakeLists.txt vendored Normal file
View File

@ -0,0 +1,4 @@
add_library(watcher INTERFACE IMPORTED GLOBAL)
set_target_properties(watcher PROPERTIES
INTERFACE_INCLUDE_DIRECTORIES ${CMAKE_CURRENT_LIST_DIR}/watcher/include
)

1
Externals/watcher/watcher vendored Submodule

@ -0,0 +1 @@
Subproject commit b03bdcfc11549df595b77239cefe2643943a3e2f

View File

@ -13,6 +13,9 @@
<uses-feature
android:name="android.hardware.gamepad"
android:required="false"/>
<uses-feature
android:name="android.hardware.microphone"
android:required="false"/>
<uses-feature
android:name="android.software.leanback"
android:required="false"/>
@ -25,12 +28,8 @@
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="com.android.providers.tv.permission.READ_EPG_DATA"/>
<uses-permission android:name="com.android.providers.tv.permission.WRITE_EPG_DATA"/>
<uses-permission
android:name="android.permission.VIBRATE"
android:required="false"/>
<uses-permission
android:name="android.permission.RECORD_AUDIO"
android:required="false"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.RECORD_AUDIO"/>
<application
android:name=".DolphinApplication"

View File

@ -0,0 +1,28 @@
package org.dolphinemu.dolphinemu.utils
import android.content.Context
import android.media.AudioManager
import androidx.annotation.Keep
import org.dolphinemu.dolphinemu.DolphinApplication
object AudioUtils {
@JvmStatic @Keep
fun getSampleRate(): Int =
getAudioServiceProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE, 48000)
@JvmStatic @Keep
fun getFramesPerBuffer(): Int =
getAudioServiceProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER, 256)
private fun getAudioServiceProperty(property: String, fallback: Int): Int {
return try {
val context = DolphinApplication.getAppContext()
val am = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
Integer.parseUnsignedInt(am.getProperty(property))
} catch (e: NullPointerException) {
fallback
} catch (e: NumberFormatException) {
fallback
}
}
}

View File

@ -122,6 +122,10 @@ static jmethodID s_permission_handler_request_record_audio_permission;
static jmethodID s_runnable_run;
static jclass s_audio_utils_class;
static jmethodID s_audio_utils_get_sample_rate;
static jmethodID s_audio_utils_get_frames_per_buffer;
namespace IDCache
{
JNIEnv* GetEnvForThread()
@ -562,6 +566,21 @@ jmethodID GetRunnableRun()
return s_runnable_run;
}
jclass GetAudioUtilsClass()
{
return s_audio_utils_class;
}
jmethodID GetAudioUtilsGetSampleRate()
{
return s_audio_utils_get_sample_rate;
}
jmethodID GetAudioUtilsGetFramesPerBuffer()
{
return s_audio_utils_get_frames_per_buffer;
}
} // namespace IDCache
extern "C" {
@ -798,6 +817,13 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
s_runnable_run = env->GetMethodID(runnable_class, "run", "()V");
env->DeleteLocalRef(runnable_class);
const jclass audio_utils_class = env->FindClass("org/dolphinemu/dolphinemu/utils/AudioUtils");
s_audio_utils_class = reinterpret_cast<jclass>(env->NewGlobalRef(audio_utils_class));
s_audio_utils_get_sample_rate = env->GetStaticMethodID(audio_utils_class, "getSampleRate", "()I");
s_audio_utils_get_frames_per_buffer =
env->GetStaticMethodID(audio_utils_class, "getFramesPerBuffer", "()I");
env->DeleteLocalRef(audio_utils_class);
return JNI_VERSION;
}
@ -834,5 +860,6 @@ JNIEXPORT void JNI_OnUnload(JavaVM* vm, void* reserved)
env->DeleteGlobalRef(s_core_device_control_class);
env->DeleteGlobalRef(s_input_detector_class);
env->DeleteGlobalRef(s_permission_handler_class);
env->DeleteGlobalRef(s_audio_utils_class);
}
}

View File

@ -121,4 +121,8 @@ jmethodID GetPermissionHandlerRequestRecordAudioPermission();
jmethodID GetRunnableRun();
jclass GetAudioUtilsClass();
jmethodID GetAudioUtilsGetSampleRate();
jmethodID GetAudioUtilsGetFramesPerBuffer();
} // namespace IDCache

View File

@ -57,17 +57,17 @@ PRIVATE
target_include_directories(main
PRIVATE
${CMAKE_SOURCE_DIR}/Externals/libadrenotools/include
${CMAKE_SOURCE_DIR}/Externals/VulkanMemoryAllocator/include
${CMAKE_CURRENT_SOURCE_DIR}/../../../Externals/libadrenotools/include
${CMAKE_CURRENT_SOURCE_DIR}/../../../Externals/VulkanMemoryAllocator/include
)
file(MAKE_DIRECTORY ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/)
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/)
file(COPY ${CMAKE_SOURCE_DIR}/Data/Sys DESTINATION ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/)
file(MAKE_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Android/app/src/main/assets/)
file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Android/app/src/main/assets/Sys/)
file(COPY ${CMAKE_CURRENT_SOURCE_DIR}/../../../Data/Sys DESTINATION ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Android/app/src/main/assets/)
# Delete folders that aren't used by the Android version of Dolphin
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/Resources/)
file(REMOVE_RECURSE ${CMAKE_SOURCE_DIR}/Source/Android/app/src/main/assets/Sys/Themes/)
file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Android/app/src/main/assets/Sys/Resources/)
file(REMOVE_RECURSE ${CMAKE_CURRENT_SOURCE_DIR}/../../../Source/Android/app/src/main/assets/Sys/Themes/)
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} main)

View File

@ -55,14 +55,14 @@ JNIEXPORT jboolean JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_ControlGroup_getEnabled(
JNIEnv* env, jobject obj)
{
return static_cast<jboolean>(GetPointer(env, obj)->enabled);
return static_cast<jboolean>(GetPointer(env, obj)->enabled.GetValue());
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_ControlGroup_setEnabled(
JNIEnv* env, jobject obj, jboolean value)
{
GetPointer(env, obj)->enabled = value;
GetPointer(env, obj)->enabled.SetValue(value);
}
JNIEXPORT jint JNICALL

View File

@ -16,6 +16,7 @@
#include "AudioCommon/WASAPIStream.h"
#include "Common/FileUtil.h"
#include "Common/Logging/Log.h"
#include "Common/TimeUtil.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
#include "Core/System.h"
@ -166,7 +167,8 @@ void UpdateSoundStream(Core::System& system)
if (sound_stream)
{
int volume = Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME);
int const volume =
Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME);
sound_stream->SetVolume(volume);
}
}
@ -192,7 +194,7 @@ void SetSoundStreamRunning(Core::System& system, bool running)
void SendAIBuffer(Core::System& system, const short* samples, unsigned int num_samples)
{
SoundStream* sound_stream = system.GetSoundStream();
const SoundStream* const sound_stream = system.GetSoundStream();
if (!sound_stream)
return;
@ -212,14 +214,17 @@ void SendAIBuffer(Core::System& system, const short* samples, unsigned int num_s
void StartAudioDump(Core::System& system)
{
SoundStream* sound_stream = system.GetSoundStream();
const SoundStream* const sound_stream = system.GetSoundStream();
std::time_t start_time = std::time(nullptr);
std::time_t const start_time = std::time(nullptr);
std::string path_prefix = File::GetUserPath(D_DUMPAUDIO_IDX) + SConfig::GetInstance().GetGameID();
std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, fmt::localtime(start_time));
const auto local_time = Common::LocalTime(start_time);
if (!local_time)
return;
std::string base_name = fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, *local_time);
const std::string audio_file_name_dtk = fmt::format("{}_dtkdump.wav", base_name);
const std::string audio_file_name_dsp = fmt::format("{}_dspdump.wav", base_name);
@ -232,7 +237,7 @@ void StartAudioDump(Core::System& system)
void StopAudioDump(Core::System& system)
{
SoundStream* sound_stream = system.GetSoundStream();
const SoundStream* const sound_stream = system.GetSoundStream();
if (!sound_stream)
return;
@ -265,7 +270,7 @@ void DecreaseVolume(Core::System& system, unsigned short offset)
void ToggleMuteVolume(Core::System& system)
{
bool isMuted = Config::Get(Config::MAIN_AUDIO_MUTED);
bool const isMuted = Config::Get(Config::MAIN_AUDIO_MUTED);
Config::SetBaseOrCurrent(Config::MAIN_AUDIO_MUTED, !isMuted);
UpdateSoundStream(system);
}

View File

@ -3,7 +3,6 @@
#pragma once
#include <memory>
#include <string>
#include <string_view>
#include <vector>

View File

@ -10,7 +10,6 @@
#include "Common/Event.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
#include "Common/Thread.h"
#include "Core/Config/MainSettings.h"
#ifdef _WIN32
@ -23,7 +22,7 @@ constexpr u32 BUFFER_SAMPLES = 512;
long CubebStream::DataCallback(cubeb_stream* stream, void* user_data, const void* /*input_buffer*/,
void* output_buffer, long num_frames)
{
auto* self = static_cast<CubebStream*>(user_data);
const auto* const self = static_cast<CubebStream*>(user_data);
if (self->m_stereo)
self->m_mixer->Mix(static_cast<short*>(output_buffer), num_frames);
@ -44,7 +43,7 @@ CubebStream::CubebStream()
Common::Event sync_event;
m_work_queue.Push([this, &sync_event] {
Common::ScopeGuard sync_event_guard([&sync_event] { sync_event.Set(); });
auto result = ::CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
auto const result = CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
m_coinit_success = result == S_OK;
m_should_couninit = result == S_OK || result == S_FALSE;
});

View File

@ -3,8 +3,6 @@
#pragma once
#include <cstddef>
#include <functional>
#include <memory>
#include <vector>

View File

@ -182,7 +182,8 @@ std::size_t Mixer::MixSurround(float* samples, std::size_t num_samples)
memset(samples, 0, num_samples * SURROUND_CHANNELS * sizeof(float));
std::size_t needed_frames = m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples);
std::size_t const needed_frames =
m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples);
constexpr std::size_t max_samples = 0x8000;
ASSERT_MSG(AUDIO, needed_frames <= max_samples,
@ -190,7 +191,7 @@ std::size_t Mixer::MixSurround(float* samples, std::size_t num_samples)
needed_frames, max_samples);
std::array<s16, max_samples> buffer;
std::size_t available_frames = Mix(buffer.data(), static_cast<std::size_t>(needed_frames));
std::size_t const available_frames = Mix(buffer.data(), static_cast<std::size_t>(needed_frames));
if (available_frames != needed_frames)
{
ERROR_LOG_FMT(AUDIO,
@ -229,7 +230,7 @@ void Mixer::PushSamples(const s16* samples, std::size_t num_samples)
if (m_log_dsp_audio)
{
const s32 sample_rate_divisor = m_dma_mixer.GetInputSampleRateDivisor();
auto volume = m_dma_mixer.GetVolume();
auto const volume = m_dma_mixer.GetVolume();
m_wave_writer_dsp.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
}
@ -241,7 +242,7 @@ void Mixer::PushStreamingSamples(const s16* samples, std::size_t num_samples)
if (m_log_dtk_audio)
{
const s32 sample_rate_divisor = m_streaming_mixer.GetInputSampleRateDivisor();
auto volume = m_streaming_mixer.GetVolume();
auto const volume = m_streaming_mixer.GetVolume();
m_wave_writer_dtk.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
}
@ -286,7 +287,8 @@ void Mixer::PushSkylanderPortalSamples(const u8* samples, std::size_t num_sample
{
for (std::size_t i = 0; i < num_samples; ++i)
{
s16 sample = static_cast<u16>(samples[i * 2 + 1]) << 8 | static_cast<u16>(samples[i * 2]);
s16 const sample =
static_cast<u16>(samples[i * 2 + 1]) << 8 | static_cast<u16>(samples[i * 2]);
samples_stereo[i * 2] = sample;
samples_stereo[i * 2 + 1] = sample;
}
@ -335,7 +337,8 @@ void Mixer::StartLogDTKAudio(const std::string& filename)
{
if (!m_log_dtk_audio)
{
bool success = m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
bool const success =
m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
if (success)
{
m_log_dtk_audio = true;
@ -372,7 +375,7 @@ void Mixer::StartLogDSPAudio(const std::string& filename)
{
if (!m_log_dsp_audio)
{
bool success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
bool const success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
if (success)
{
m_log_dsp_audio = true;
@ -494,10 +497,10 @@ void Mixer::MixerFifo::Enqueue()
0.0002984010f, 0.0002102045f, 0.0001443499f, 0.0000961509f, 0.0000616906f, 0.0000377350f,
0.0000216492f, 0.0000113187f, 0.0000050749f, 0.0000016272f};
const std::size_t head = m_queue_head.load(std::memory_order_acquire);
std::size_t const head = m_queue_head.load(std::memory_order_acquire);
// Check if we run out of space in the circular queue. (rare)
std::size_t next_head = (head + 1) & GRANULE_QUEUE_MASK;
std::size_t const next_head = (head + 1) & GRANULE_QUEUE_MASK;
if (next_head == m_queue_tail.load(std::memory_order_acquire))
{
WARN_LOG_FMT(AUDIO,

View File

@ -3,11 +3,9 @@
#pragma once
#include <algorithm>
#include <array>
#include <atomic>
#include <bit>
#include <cmath>
#include "AudioCommon/SurroundDecoder.h"
#include "AudioCommon/WaveFile.h"

View File

@ -76,7 +76,7 @@ static bool InitLibrary()
if (!InitFunctions())
{
::FreeLibrary(s_openal_dll);
FreeLibrary(s_openal_dll);
s_openal_dll = nullptr;
return false;
}
@ -168,7 +168,7 @@ bool OpenALStream::SetRunning(bool running)
static ALenum CheckALError(const char* desc)
{
ALenum err = palGetError();
ALenum const err = palGetError();
if (err != AL_NO_ERROR)
{
@ -211,16 +211,16 @@ void OpenALStream::SoundLoop()
{
Common::SetCurrentThreadName("Audio thread - openal");
bool float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0;
bool surround_capable = palIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi();
bool const float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0;
bool const surround_capable = palIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi();
bool use_surround = Config::ShouldUseDPL2Decoder() && surround_capable;
// As there is no extension to check for 32-bit fixed point support
// and we know that only a X-Fi with hardware OpenAL supports it,
// we just check if one is being used.
bool fixed32_capable = IsCreativeXFi();
bool const fixed32_capable = IsCreativeXFi();
u32 frequency = m_mixer->GetSampleRate();
u32 const frequency = m_mixer->GetSampleRate();
u32 frames_per_buffer;
// Can't have zero samples per buffer
@ -288,12 +288,12 @@ void OpenALStream::SoundLoop()
num_buffers_queued -= num_buffers_processed;
}
unsigned int min_frames = frames_per_buffer;
unsigned int const min_frames = frames_per_buffer;
if (use_surround)
{
std::array<float, OAL_MAX_FRAMES * SURROUND_CHANNELS> dpl2;
u32 rendered_frames = static_cast<u32>(m_mixer->MixSurround(dpl2.data(), min_frames));
u32 const rendered_frames = static_cast<u32>(m_mixer->MixSurround(dpl2.data(), min_frames));
if (rendered_frames < min_frames)
continue;
@ -351,7 +351,8 @@ void OpenALStream::SoundLoop()
}
else
{
u32 rendered_frames = static_cast<u32>(m_mixer->Mix(m_realtime_buffer.data(), min_frames));
u32 const rendered_frames =
static_cast<u32>(m_mixer->Mix(m_realtime_buffer.data(), min_frames));
if (!rendered_frames)
continue;

View File

@ -7,9 +7,6 @@
#include "AudioCommon/SoundStream.h"
#include "Common/Event.h"
#include "Core/Core.h"
#include "Core/HW/AudioInterface.h"
#include "Core/HW/SystemTimers.h"
#ifdef _WIN32
#include <al.h>

View File

@ -8,40 +8,27 @@
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#include <jni.h>
#include "Common/Assert.h"
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Core/ConfigManager.h"
#include "jni/AndroidCommon/IDCache.h"
// engine interfaces
static SLObjectItf engineObject;
static SLEngineItf engineEngine;
static SLObjectItf outputMixObject;
// buffer queue player interfaces
static SLObjectItf bqPlayerObject = nullptr;
static SLPlayItf bqPlayerPlay;
static SLAndroidSimpleBufferQueueItf bqPlayerBufferQueue;
static SLVolumeItf bqPlayerVolume;
static Mixer* g_mixer;
#define BUFFER_SIZE 512
#define BUFFER_SIZE_IN_SAMPLES (BUFFER_SIZE / 2)
// Double buffering.
static short buffer[2][BUFFER_SIZE];
static int curBuffer = 0;
static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
void OpenSLESStream::BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
{
ASSERT(bq == bqPlayerBufferQueue);
ASSERT(nullptr == context);
reinterpret_cast<OpenSLESStream*>(context)->PushSamples(bq);
}
void OpenSLESStream::PushSamples(SLAndroidSimpleBufferQueueItf bq)
{
ASSERT(bq == m_bq_player_buffer_queue);
// Render to the fresh buffer
g_mixer->Mix(reinterpret_cast<short*>(buffer[curBuffer]), BUFFER_SIZE_IN_SAMPLES);
SLresult result =
(*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[curBuffer], sizeof(buffer[0]));
curBuffer ^= 1; // Switch buffer
m_mixer->Mix(m_buffer[m_current_buffer].data(), m_frames_per_buffer);
SLresult result = (*bq)->Enqueue(bq, m_buffer[m_current_buffer].data(), m_bytes_per_buffer);
m_current_buffer ^= 1; // Switch buffer
// Comment from sample code:
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
@ -51,61 +38,78 @@ static void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
bool OpenSLESStream::Init()
{
JNIEnv* env = IDCache::GetEnvForThread();
jclass audio_utils = IDCache::GetAudioUtilsClass();
const SLuint32 sample_rate =
env->CallStaticIntMethod(audio_utils, IDCache::GetAudioUtilsGetSampleRate());
m_frames_per_buffer =
env->CallStaticIntMethod(audio_utils, IDCache::GetAudioUtilsGetFramesPerBuffer());
INFO_LOG_FMT(AUDIO, "OpenSLES configuration: {} Hz, {} frames per buffer", sample_rate,
m_frames_per_buffer);
constexpr SLuint32 channels = 2;
const SLuint32 samples_per_buffer = m_frames_per_buffer * channels;
m_bytes_per_buffer = m_frames_per_buffer * channels * sizeof(m_buffer[0][0]);
for (std::vector<short>& buffer : m_buffer)
buffer.resize(samples_per_buffer);
SLresult result;
// create engine
result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
result = slCreateEngine(&m_engine_object, 0, nullptr, 0, nullptr, nullptr);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
result = (*m_engine_object)->Realize(m_engine_object, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
result = (*m_engine_object)->GetInterface(m_engine_object, SL_IID_ENGINE, &m_engine_engine);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
result = (*m_engine_engine)->CreateOutputMix(m_engine_engine, &m_output_mix_object, 0, 0, 0);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
result = (*m_output_mix_object)->Realize(m_output_mix_object, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
SLDataFormat_PCM format_pcm = {SL_DATAFORMAT_PCM,
2,
m_mixer->GetSampleRate() * 1000,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16,
SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN};
SLDataFormat_PCM format_pcm = {
SL_DATAFORMAT_PCM, channels,
sample_rate * 1000, SL_PCMSAMPLEFORMAT_FIXED_16,
SL_PCMSAMPLEFORMAT_FIXED_16, SL_SPEAKER_FRONT_LEFT | SL_SPEAKER_FRONT_RIGHT,
SL_BYTEORDER_LITTLEENDIAN};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, m_output_mix_object};
SLDataSink audioSnk = {&loc_outmix, nullptr};
// create audio player
const SLInterfaceID ids[2] = {SL_IID_BUFFERQUEUE, SL_IID_VOLUME};
const SLboolean req[2] = {SL_BOOLEAN_TRUE, SL_BOOLEAN_TRUE};
result =
(*engineEngine)
->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
result = (*m_engine_engine)
->CreateAudioPlayer(m_engine_engine, &m_bq_player_object, &audioSrc, &audioSnk, 2,
ids, req);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
result = (*m_bq_player_object)->Realize(m_bq_player_object, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
result = (*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_PLAY, &m_bq_player_play);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_bq_player_object)
->GetInterface(m_bq_player_object, SL_IID_BUFFERQUEUE, &m_bq_player_buffer_queue);
ASSERT(SL_RESULT_SUCCESS == result);
result =
(*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);
(*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_VOLUME, &m_bq_player_volume);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
result = (*m_bq_player_buffer_queue)
->RegisterCallback(m_bq_player_buffer_queue, BQPlayerCallback, this);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
result = (*m_bq_player_play)->SetPlayState(m_bq_player_play, SL_PLAYSTATE_PLAYING);
ASSERT(SL_RESULT_SUCCESS == result);
// Render and enqueue a first buffer.
curBuffer ^= 1;
g_mixer = m_mixer.get();
m_current_buffer ^= 1;
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[0], sizeof(buffer[0]));
result = (*m_bq_player_buffer_queue)
->Enqueue(m_bq_player_buffer_queue, m_buffer[0].data(), m_bytes_per_buffer);
if (SL_RESULT_SUCCESS != result)
return false;
@ -114,39 +118,39 @@ bool OpenSLESStream::Init()
OpenSLESStream::~OpenSLESStream()
{
if (bqPlayerObject != nullptr)
if (m_bq_player_object != nullptr)
{
(*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = nullptr;
bqPlayerPlay = nullptr;
bqPlayerBufferQueue = nullptr;
bqPlayerVolume = nullptr;
(*m_bq_player_object)->Destroy(m_bq_player_object);
m_bq_player_object = nullptr;
m_bq_player_play = nullptr;
m_bq_player_buffer_queue = nullptr;
m_bq_player_volume = nullptr;
}
if (outputMixObject != nullptr)
if (m_output_mix_object != nullptr)
{
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = nullptr;
(*m_output_mix_object)->Destroy(m_output_mix_object);
m_output_mix_object = nullptr;
}
if (engineObject != nullptr)
if (m_engine_object != nullptr)
{
(*engineObject)->Destroy(engineObject);
engineObject = nullptr;
engineEngine = nullptr;
(*m_engine_object)->Destroy(m_engine_object);
m_engine_object = nullptr;
m_engine_engine = nullptr;
}
}
bool OpenSLESStream::SetRunning(bool running)
{
SLuint32 new_state = running ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED;
return (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, new_state) == SL_RESULT_SUCCESS;
return (*m_bq_player_play)->SetPlayState(m_bq_player_play, new_state) == SL_RESULT_SUCCESS;
}
void OpenSLESStream::SetVolume(int volume)
{
const SLmillibel attenuation =
volume <= 0 ? SL_MILLIBEL_MIN : static_cast<SLmillibel>(2000 * std::log10(volume / 100.0f));
(*bqPlayerVolume)->SetVolumeLevel(bqPlayerVolume, attenuation);
(*m_bq_player_volume)->SetVolumeLevel(m_bq_player_volume, attenuation);
}
#endif // HAVE_OPENSL_ES

View File

@ -3,10 +3,15 @@
#pragma once
#include <thread>
#ifdef HAVE_OPENSL_ES
#include <array>
#include <vector>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#endif // HAVE_OPENSL_ES
#include "AudioCommon/SoundStream.h"
#include "Common/Event.h"
class OpenSLESStream final : public SoundStream
{
@ -19,7 +24,25 @@ public:
static bool IsValid() { return true; }
private:
std::thread thread;
Common::Event soundSyncEvent;
static void BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context);
void PushSamples(SLAndroidSimpleBufferQueueItf bq);
// engine interfaces
SLObjectItf m_engine_object;
SLEngineItf m_engine_engine;
SLObjectItf m_output_mix_object;
// buffer queue player interfaces
SLObjectItf m_bq_player_object = nullptr;
SLPlayItf m_bq_player_play;
SLAndroidSimpleBufferQueueItf m_bq_player_buffer_queue;
SLVolumeItf m_bq_player_volume;
SLuint32 m_frames_per_buffer;
SLuint32 m_bytes_per_buffer;
// Double buffering.
std::array<std::vector<short>, 2> m_buffer;
int m_current_buffer = 0;
#endif // HAVE_OPENSL_ES
};

View File

@ -8,7 +8,6 @@
#endif
#include "AudioCommon/SoundStream.h"
#include "Common/CommonTypes.h"
#include "Common/Flag.h"
#include "Common/Thread.h"

View File

@ -32,7 +32,7 @@ size_t SurroundDecoder::QueryFramesNeededForSurroundOutput(const size_t output_f
if (m_decoded_fifo.size() < output_frames * SURROUND_CHANNELS)
{
// Output stereo frames needed to have at least the desired number of surround frames
size_t frames_needed = output_frames - m_decoded_fifo.size() / SURROUND_CHANNELS;
size_t const frames_needed = output_frames - m_decoded_fifo.size() / SURROUND_CHANNELS;
return frames_needed + m_frame_block_size - frames_needed % m_frame_block_size;
}

View File

@ -8,7 +8,6 @@
// clang-format off
#include <Audioclient.h>
#include <mmdeviceapi.h>
#include <devpkey.h>
#include <functiondiscoverykeys_devpkey.h>
#include <wil/resource.h>
// clang-format on
@ -159,8 +158,9 @@ ComPtr<IMMDevice> WASAPIStream::GetDeviceByName(std::string_view name)
bool WASAPIStream::Init()
{
ASSERT(m_enumerator == nullptr);
HRESULT result = CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(m_enumerator.GetAddressOf()));
HRESULT const result =
CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(m_enumerator.GetAddressOf()));
if (!HandleWinAPI("Failed to create MMDeviceEnumerator", result))
return false;

View File

@ -32,7 +32,7 @@ class WASAPIStream final : public SoundStream
#ifdef _WIN32
public:
explicit WASAPIStream();
~WASAPIStream();
~WASAPIStream() override;
bool Init() override;
bool SetRunning(bool running) override;

View File

@ -69,7 +69,7 @@ if (APPLE AND ENABLE_QT)
if (MACOS_CODE_SIGNING)
add_custom_command(TARGET build_final_bundle
POST_BUILD
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/../../Tools/mac-codesign.sh"
"-t"
"${MACOS_CODE_SIGNING_IDENTITY}"
"${DOLPHIN_MAC_BUNDLE}/Contents/Helpers/Dolphin Updater.app")
@ -79,9 +79,9 @@ if (APPLE AND ENABLE_QT)
if (MACOS_CODE_SIGNING)
add_custom_command(TARGET build_final_bundle
POST_BUILD
COMMAND "${CMAKE_SOURCE_DIR}/Tools/mac-codesign.sh"
COMMAND "${CMAKE_CURRENT_SOURCE_DIR}/../../Tools/mac-codesign.sh"
"-t"
"-e" "${CMAKE_SOURCE_DIR}/Source/Core/DolphinQt/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements"
"-e" "${CMAKE_CURRENT_SOURCE_DIR}/../../Source/Core/DolphinQt/DolphinEmu$<$<CONFIG:Debug>:Debug>.entitlements"
"${MACOS_CODE_SIGNING_IDENTITY}"
"${DOLPHIN_MAC_BUNDLE}")
endif()

View File

@ -31,7 +31,7 @@ public:
{
m_active_block = &m_output_result.blocks.emplace_back(base_addr);
}
virtual ~GekkoIRPlugin() = default;
~GekkoIRPlugin() override = default;
void OnDirectivePre(GekkoDirective directive) override;
void OnDirectivePost(GekkoDirective directive) override;

View File

@ -64,6 +64,8 @@ add_library(common
FatFsUtil.h
FileSearch.cpp
FileSearch.h
FilesystemWatcher.cpp
FilesystemWatcher.h
FileUtil.cpp
FileUtil.h
FixedSizeQueue.h
@ -176,7 +178,7 @@ PUBLIC
enet::enet
fmt::fmt
MbedTLS::mbedtls
minizip::minizip
minizip-ng::minizip-ng
sfml-network
PRIVATE
@ -184,6 +186,7 @@ PRIVATE
FatFs
Iconv::Iconv
spng::spng
watcher
${VTUNE_LIBRARIES}
)

View File

@ -46,8 +46,7 @@ public:
ASSERT(!mbedtls_aes_setkey_dec(&ctx, key, 128));
}
virtual bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out,
size_t len) const override
bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out, size_t len) const override
{
std::array<u8, BLOCK_SIZE> iv_tmp{};
if (iv)
@ -206,8 +205,7 @@ public:
_mm_storeu_si128(&((__m128i*)buf_out)[d], block[d]);
}
virtual bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out,
size_t len) const override
bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out, size_t len) const override
{
if (len % BLOCK_SIZE)
return false;

View File

@ -41,18 +41,18 @@ public:
mbedtls_sha1_init(&ctx);
ASSERT(!mbedtls_sha1_starts_ret(&ctx));
}
~ContextMbed() { mbedtls_sha1_free(&ctx); }
virtual void Update(const u8* msg, size_t len) override
~ContextMbed() override { mbedtls_sha1_free(&ctx); }
void Update(const u8* msg, size_t len) override
{
ASSERT(!mbedtls_sha1_update_ret(&ctx, msg, len));
}
virtual Digest Finish() override
Digest Finish() override
{
Digest digest;
ASSERT(!mbedtls_sha1_finish_ret(&ctx, digest.data()));
return digest;
}
virtual bool HwAccelerated() const override { return false; }
bool HwAccelerated() const override { return false; }
private:
mbedtls_sha1_context ctx{};
@ -204,7 +204,7 @@ private:
}
ATTRIBUTE_TARGET("sha")
virtual void ProcessBlock(const u8* msg) override
void ProcessBlock(const u8* msg) override
{
// There are 80 rounds with 4 bytes per round, giving 0x140 byte work space, but we can keep
// active state in just 0x40 bytes.
@ -248,7 +248,7 @@ private:
// clang-format on
}
virtual Digest GetDigest() override
Digest GetDigest() override
{
Digest digest;
_mm_storeu_si128((__m128i*)&digest[0], byterev_16B(state[0]));
@ -257,7 +257,7 @@ private:
return digest;
}
virtual bool HwAccelerated() const override { return true; }
bool HwAccelerated() const override { return true; }
std::array<XmmReg, 2> state{};
};

View File

@ -25,6 +25,7 @@
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/TimeUtil.h"
#include "Core/Config/MainSettings.h"
@ -95,12 +96,7 @@ int SDCardDiskIOCtl(File::IOFile* image, u8 pdrv, u8 cmd, void* buff)
u32 GetSystemTimeFAT()
{
const std::time_t time = std::time(nullptr);
std::tm tm;
#ifdef _WIN32
localtime_s(&tm, &time);
#else
localtime_r(&time, &tm);
#endif
std::tm tm = *Common::LocalTime(time);
DWORD fattime = 0;
fattime |= (tm.tm_year - 80) << 25;

View File

@ -0,0 +1,67 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/FilesystemWatcher.h"
#include <wtr/watcher.hpp>
#include "Common/Logging/Log.h"
#include "Common/StringUtil.h"
namespace Common
{
FilesystemWatcher::FilesystemWatcher() = default;
FilesystemWatcher::~FilesystemWatcher() = default;
void FilesystemWatcher::Watch(const std::string& path)
{
const auto [iter, inserted] = m_watched_paths.try_emplace(path, nullptr);
if (inserted)
{
iter->second = std::make_unique<wtr::watch>(path, [this](wtr::event e) {
const auto watched_path = PathToString(e.path_name);
if (e.path_type == wtr::event::path_type::watcher)
{
if (watched_path.starts_with('e'))
ERROR_LOG_FMT(COMMON, "Filesystem watcher: '{}'", watched_path);
else if (watched_path.starts_with('w'))
WARN_LOG_FMT(COMMON, "Filesystem watcher: '{}'", watched_path);
return;
}
if (e.effect_type == wtr::event::effect_type::create)
{
const auto path = WithUnifiedPathSeparators(watched_path);
PathAdded(path);
}
else if (e.effect_type == wtr::event::effect_type::modify)
{
const auto path = WithUnifiedPathSeparators(watched_path);
PathModified(path);
}
else if (e.effect_type == wtr::event::effect_type::rename)
{
if (!e.associated)
{
WARN_LOG_FMT(COMMON, "Rename on path '{}' seen without association!", watched_path);
return;
}
const auto old_path = WithUnifiedPathSeparators(watched_path);
const auto new_path = WithUnifiedPathSeparators(PathToString(e.associated->path_name));
PathRenamed(old_path, new_path);
}
else if (e.effect_type == wtr::event::effect_type::destroy)
{
const auto path = WithUnifiedPathSeparators(watched_path);
PathDeleted(path);
}
});
}
}
void FilesystemWatcher::Unwatch(const std::string& path)
{
m_watched_paths.erase(path);
}
} // namespace Common

View File

@ -0,0 +1,47 @@
// Copyright 2025 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <map>
#include <memory>
#include <string>
#include <string_view>
namespace wtr
{
inline namespace watcher
{
class watch;
}
} // namespace wtr
namespace Common
{
// A class that can watch a path and receive callbacks
// when files or directories underneath that path receive events
class FilesystemWatcher
{
public:
FilesystemWatcher();
virtual ~FilesystemWatcher();
void Watch(const std::string& path);
void Unwatch(const std::string& path);
private:
// A new file or folder was added to one of the watched paths
virtual void PathAdded(std::string_view path) {}
// A file or folder was modified in one of the watched paths
virtual void PathModified(std::string_view path) {}
// A file or folder was renamed in one of the watched paths
virtual void PathRenamed(std::string_view old_path, std::string_view new_path) {}
// A file or folder was deleted in one of the watched paths
virtual void PathDeleted(std::string_view path) {}
std::map<std::string, std::unique_ptr<wtr::watch>> m_watched_paths;
};
} // namespace Common

View File

@ -10,9 +10,9 @@
class GLContextWGL final : public GLContext
{
public:
~GLContextWGL();
~GLContextWGL() override;
bool IsHeadless() const;
bool IsHeadless() const override;
std::unique_ptr<GLContext> CreateSharedContext() override;

View File

@ -101,7 +101,7 @@ class HostDisassemblerBochs final : public HostDisassembler
{
public:
explicit HostDisassemblerBochs();
~HostDisassemblerBochs() = default;
~HostDisassemblerBochs() override = default;
private:
disassembler m_disasm;

View File

@ -9,7 +9,7 @@ class ConsoleListener : public Common::Log::LogListener
{
public:
ConsoleListener();
~ConsoleListener();
~ConsoleListener() override;
void Log(Common::Log::LogLevel level, const char* text) override;

View File

@ -5,7 +5,9 @@
#include <algorithm>
#include <unzip.h>
#include <mz.h>
#include <mz_zip.h>
#include <mz_zip_rw.h>
#include "Common/CommonTypes.h"
#include "Common/ScopeGuard.h"
@ -13,14 +15,14 @@
namespace Common
{
// Reads all of the current file. destination must be big enough to fit the whole file.
inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
inline bool ReadFileFromZip(void* zip_reader, u8* destination, u64 len)
{
const u64 MAX_BUFFER_SIZE = 65535;
if (unzOpenCurrentFile(file) != UNZ_OK)
if (mz_zip_reader_entry_open(zip_reader) != MZ_OK)
return false;
Common::ScopeGuard guard{[&] { unzCloseCurrentFile(file); }};
Common::ScopeGuard guard{[&] { mz_zip_reader_entry_close(zip_reader); }};
u64 bytes_to_go = len;
while (bytes_to_go > 0)
@ -28,7 +30,7 @@ inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
// NOTE: multiples of 4G can't cause read_len == 0 && bytes_to_go > 0, as MAX_BUFFER_SIZE is
// small.
const u32 read_len = static_cast<u32>(std::min(bytes_to_go, MAX_BUFFER_SIZE));
const int rv = unzReadCurrentFile(file, destination, read_len);
const int rv = mz_zip_reader_entry_read(zip_reader, destination, read_len);
if (rv < 0)
return false;
@ -37,11 +39,11 @@ inline bool ReadFileFromZip(unzFile file, u8* destination, u64 len)
destination += bytes_read;
}
return unzEndOfFile(file) == 1;
return bytes_to_go == 0;
}
template <typename ContiguousContainer>
bool ReadFileFromZip(unzFile file, ContiguousContainer* destination)
bool ReadFileFromZip(void* file, ContiguousContainer* destination)
{
return ReadFileFromZip(file, reinterpret_cast<u8*>(destination->data()), destination->size());
}

View File

@ -122,7 +122,6 @@ std::string SettingsWriter::GenerateSerialNumber()
// Must be 9 characters at most; otherwise the serial number will be rejected by SDK libraries,
// as there is a check to ensure the string length is strictly lower than 10.
// 3 for %j, 2 for %H, 2 for %M, 2 for %S.
return fmt::format("{:%j%H%M%S}", fmt::localtime(t));
return fmt::format("{:09}", t % 1000000000);
}
} // namespace Common

View File

@ -2,23 +2,25 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include "Common/TimeUtil.h"
#include "Common/Logging/Log.h"
#include <ctime>
#include <optional>
namespace Common
{
std::optional<std::tm> Localtime(std::time_t time)
std::optional<std::tm> LocalTime(std::time_t time)
{
std::tm local_time;
#ifdef _MSC_VER
if (localtime_s(&local_time, &time) != 0)
return std::nullopt;
#else
std::tm* result = localtime_r(&time, &local_time);
if (result != &local_time)
return std::nullopt;
if (localtime_r(&time, &local_time) == NULL)
#endif
{
ERROR_LOG_FMT(COMMON, "Failed to convert time to local time: {}", std::strerror(errno));
return std::nullopt;
}
return local_time;
}
} // Namespace Common

View File

@ -9,5 +9,5 @@
namespace Common
{
// Threadsafe and error-checking variant of std::localtime()
std::optional<std::tm> Localtime(std::time_t time);
std::optional<std::tm> LocalTime(std::time_t time);
} // Namespace Common

View File

@ -165,17 +165,26 @@ void AchievementManager::LoadGame(const DiscIO::Volume* volume)
{
return;
}
if (volume == nullptr)
{
WARN_LOG_FMT(ACHIEVEMENTS, "Called Load Game without a game.");
return;
}
if (!m_client)
{
ERROR_LOG_FMT(ACHIEVEMENTS,
"Attempted to load game achievements without achievement client initialized.");
return;
}
if (volume == nullptr)
{
WARN_LOG_FMT(ACHIEVEMENTS, "Software format unsupported by AchievementManager.");
if (rc_client_get_game_info(m_client))
{
rc_client_begin_change_media_from_hash(m_client, "", ChangeMediaCallback, NULL);
}
else
{
rc_client_set_read_memory_function(m_client, MemoryVerifier);
rc_client_begin_load_game(m_client, "", LoadGameCallback, NULL);
}
return;
}
rc_client_set_unofficial_enabled(m_client, Config::Get(Config::RA_UNOFFICIAL_ENABLED));
rc_client_set_encore_mode_enabled(m_client, Config::Get(Config::RA_ENCORE_ENABLED));
rc_client_set_spectator_mode_enabled(m_client, Config::Get(Config::RA_SPECTATOR_ENABLED));
@ -329,11 +338,12 @@ void AchievementManager::DoFrame()
if (!system)
return;
Core::CPUThreadGuard thread_guard(*system);
u32 mem2_size = system->GetMemory().GetExRamSizeReal();
u32 mem2_size = (system->IsWii()) ? system->GetMemory().GetExRamSizeReal() : 0;
if (m_cloned_memory.size() != MEM1_SIZE + mem2_size)
m_cloned_memory.resize(MEM1_SIZE + mem2_size);
system->GetMemory().CopyFromEmu(m_cloned_memory.data(), 0, MEM1_SIZE);
system->GetMemory().CopyFromEmu(m_cloned_memory.data() + MEM1_SIZE, MEM2_START, mem2_size);
if (mem2_size > 0)
system->GetMemory().CopyFromEmu(m_cloned_memory.data() + MEM1_SIZE, MEM2_START, mem2_size);
}
#endif // RC_CLIENT_SUPPORTS_RAINTEGRATION
std::lock_guard lg{m_lock};
@ -598,11 +608,6 @@ rc_client_t* AchievementManager::GetClient()
return m_client;
}
rc_api_fetch_game_data_response_t* AchievementManager::GetGameData()
{
return &m_game_data;
}
const AchievementManager::Badge& AchievementManager::GetGameBadge() const
{
return m_game_badge.data.empty() ? m_default_game_badge : m_game_badge;
@ -736,12 +741,8 @@ void AchievementManager::CloseGame()
if (Config::Get(Config::RA_DISCORD_PRESENCE_ENABLED))
Discord::UpdateDiscordPresence();
if (rc_client_get_game_info(m_client))
{
rc_api_destroy_fetch_game_data_response(&m_game_data);
rc_client_unload_game(m_client);
}
INFO_LOG_FMT(ACHIEVEMENTS, "Game closed.");
m_game_data = {};
}
m_update_callback(UpdatedItems{.all = true});
@ -995,36 +996,30 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
OSD::Color::RED);
return;
}
if (result == RC_NO_GAME_LOADED && instance.m_dll_found)
auto* game = rc_client_get_game_info(client);
if (result == RC_OK)
{
// Allow developer tools for unidentified games
rc_client_set_read_memory_function(instance.m_client, MemoryPeeker);
instance.m_system.store(&Core::System::GetInstance(), std::memory_order_release);
WARN_LOG_FMT(ACHIEVEMENTS, "Unrecognized title ready for development.");
OSD::AddMessage("Unrecognized title loaded for development.", OSD::Duration::VERY_LONG,
OSD::Color::YELLOW);
if (!game)
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve game information from client.");
OSD::AddMessage("Failed to load achievements for this title.", OSD::Duration::VERY_LONG,
OSD::Color::RED);
}
else
{
INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id);
instance.m_display_welcome_message = true;
}
}
if (result != RC_OK)
else
{
WARN_LOG_FMT(ACHIEVEMENTS, "Failed to load data for current game.");
OSD::AddMessage("Achievements are not supported for this title.", OSD::Duration::VERY_LONG,
OSD::Color::RED);
return;
}
auto* game = rc_client_get_game_info(client);
if (!game)
{
ERROR_LOG_FMT(ACHIEVEMENTS, "Failed to retrieve game information from client.");
OSD::AddMessage("Failed to load achievements for this title.", OSD::Duration::VERY_LONG,
OSD::Color::RED);
instance.CloseGame();
return;
}
INFO_LOG_FMT(ACHIEVEMENTS, "Loaded data for game ID {}.", game->id);
rc_client_set_read_memory_function(instance.m_client, MemoryPeeker);
instance.m_display_welcome_message = true;
instance.FetchGameBadges();
instance.m_system.store(&Core::System::GetInstance(), std::memory_order_release);
instance.m_update_callback({.all = true});

View File

@ -89,8 +89,8 @@ public:
static constexpr std::string_view BLUE = "#0B71C1";
static constexpr std::string_view APPROVED_LIST_FILENAME = "ApprovedInis.json";
static const inline Common::SHA1::Digest APPROVED_LIST_HASH = {
0xE1, 0x29, 0xD1, 0x33, 0x4D, 0xF2, 0xF8, 0xA8, 0x4E, 0xCA,
0xF6, 0x87, 0xE6, 0xEC, 0xEC, 0xB3, 0x18, 0x69, 0x34, 0x45};
0x6D, 0x91, 0xF5, 0xC1, 0xE2, 0x4C, 0xC3, 0x39, 0xF5, 0x7F,
0xEC, 0xA9, 0x8C, 0xA9, 0xBD, 0x61, 0x28, 0x54, 0x11, 0x62};
struct LeaderboardEntry
{
@ -160,7 +160,6 @@ public:
const Badge& GetPlayerBadge() const;
std::string_view GetGameDisplayName() const;
rc_client_t* GetClient();
rc_api_fetch_game_data_response_t* GetGameData();
const Badge& GetGameBadge() const;
const Badge& GetAchievementBadge(AchievementId id, bool locked) const;
const LeaderboardStatus* GetLeaderboardInfo(AchievementId leaderboard_id);
@ -278,9 +277,6 @@ private:
std::atomic_bool m_background_execution_allowed = true;
Badge m_player_badge;
Hash m_game_hash{};
u32 m_game_id = 0;
rc_api_fetch_game_data_response_t m_game_data{};
bool m_is_game_loaded = false;
Badge m_game_badge;
bool m_display_welcome_message = false;
std::unordered_map<AchievementId, Badge> m_unlocked_badges;

View File

@ -603,6 +603,8 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
return false;
}
AchievementManager::GetInstance().LoadGame(nullptr);
SConfig::OnTitleDirectlyBooted(guard);
ppc_state.pc = executable.reader->GetEntryPoint();
@ -635,6 +637,8 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
if (!BootNANDTitle(system, nand_title.id))
return false;
AchievementManager::GetInstance().LoadGame(nullptr);
SConfig::OnTitleDirectlyBooted(guard);
return true;
}
@ -661,6 +665,8 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
ipl.disc->auto_disc_change_paths);
}
AchievementManager::GetInstance().LoadGame(nullptr);
SConfig::OnTitleDirectlyBooted(guard);
return true;
}
@ -668,6 +674,7 @@ bool CBoot::BootUp(Core::System& system, const Core::CPUThreadGuard& guard,
bool operator()(const BootParameters::DFF& dff) const
{
NOTICE_LOG_FMT(BOOT, "Booting DFF: {}", dff.dff_path);
AchievementManager::GetInstance().LoadGame(nullptr);
return system.GetFifoPlayer().Open(dff.dff_path);
}

View File

@ -20,7 +20,7 @@ public:
explicit DolReader(const std::string& filename);
explicit DolReader(File::IOFile file);
explicit DolReader(std::vector<u8> buffer);
~DolReader();
~DolReader() override;
bool IsValid() const override { return m_is_valid; }
bool IsWii() const override { return m_is_wii; }

View File

@ -28,7 +28,7 @@ public:
explicit ElfReader(const std::string& filename);
explicit ElfReader(File::IOFile file);
explicit ElfReader(std::vector<u8> buffer);
~ElfReader();
~ElfReader() override;
u32 Read32(int off) const { return base32[off >> 2]; }
// Quick accessors
ElfType GetType() const { return (ElfType)(header->e_type); }

View File

@ -45,6 +45,7 @@ const Info<bool> MAIN_ACCURATE_CPU_CACHE{{System::Main, "Core", "AccurateCPUCach
const Info<bool> MAIN_DSP_HLE{{System::Main, "Core", "DSPHLE"}, true};
const Info<int> MAIN_MAX_FALLBACK{{System::Main, "Core", "MaxFallback"}, 100};
const Info<int> MAIN_TIMING_VARIANCE{{System::Main, "Core", "TimingVariance"}, 40};
const Info<bool> MAIN_CORRECT_TIME_DRIFT{{System::Main, "Core", "CorrectTimeDrift"}, false};
const Info<bool> MAIN_CPU_THREAD{{System::Main, "Core", "CPUThread"}, true};
const Info<bool> MAIN_SYNC_ON_SKIP_IDLE{{System::Main, "Core", "SyncOnSkipIdle"}, true};
const Info<std::string> MAIN_DEFAULT_ISO{{System::Main, "Core", "DefaultISO"}, ""};

View File

@ -63,6 +63,7 @@ extern const Info<bool> MAIN_ACCURATE_CPU_CACHE;
extern const Info<bool> MAIN_DSP_HLE;
extern const Info<int> MAIN_MAX_FALLBACK;
extern const Info<int> MAIN_TIMING_VARIANCE;
extern const Info<bool> MAIN_CORRECT_TIME_DRIFT;
extern const Info<bool> MAIN_CPU_THREAD;
extern const Info<bool> MAIN_SYNC_ON_SKIP_IDLE;
extern const Info<std::string> MAIN_DEFAULT_ISO;

View File

@ -8,6 +8,7 @@
#include <cstring>
#include <functional>
#include <mutex>
#include <optional>
#include <queue>
#include <utility>
#include <variant>
@ -34,6 +35,7 @@
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/Thread.h"
#include "Common/TimeUtil.h"
#include "Common/Version.h"
#include "Core/AchievementManager.h"
@ -82,7 +84,6 @@
#include "InputCommon/ControllerInterface/ControllerInterface.h"
#include "InputCommon/GCAdapter.h"
#include "VideoCommon/Assets/CustomAssetLoader.h"
#include "VideoCommon/AsyncRequests.h"
#include "VideoCommon/Fifo.h"
#include "VideoCommon/FrameDumper.h"
@ -528,9 +529,6 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
FreeLook::LoadInputConfig();
system.GetCustomAssetLoader().Init();
Common::ScopeGuard asset_loader_guard([&system] { system.GetCustomAssetLoader().Shutdown(); });
system.GetMovie().Init(*boot);
Common::ScopeGuard movie_guard([&system] { system.GetMovie().Shutdown(); });
@ -737,15 +735,17 @@ static std::string GenerateScreenshotFolderPath()
return path;
}
static std::string GenerateScreenshotName()
static std::optional<std::string> GenerateScreenshotName()
{
// append gameId, path only contains the folder here.
const std::string path_prefix =
GenerateScreenshotFolderPath() + SConfig::GetInstance().GetGameID();
const std::time_t cur_time = std::time(nullptr);
const std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, fmt::localtime(cur_time));
const auto local_time = Common::LocalTime(cur_time);
if (!local_time)
return std::nullopt;
const std::string base_name = fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, *local_time);
// First try a filename without any suffixes, if already exists then append increasing numbers
std::string name = fmt::format("{}.png", base_name);
@ -761,7 +761,9 @@ static std::string GenerateScreenshotName()
void SaveScreenShot()
{
const Core::CPUThreadGuard guard(Core::System::GetInstance());
g_frame_dumper->SaveScreenshot(GenerateScreenshotName());
std::optional<std::string> name = GenerateScreenshotName();
if (name)
g_frame_dumper->SaveScreenshot(*name);
}
void SaveScreenShot(std::string_view name)

View File

@ -105,10 +105,20 @@ void CoreTimingManager::Init()
m_last_oc_factor = m_config_oc_factor;
m_globals.last_OC_factor_inverted = m_config_oc_inv_factor;
m_on_state_changed_handle = Core::AddOnStateChangedCallback([this](Core::State state) {
if (state == Core::State::Running)
{
// We don't want Throttle to attempt catch-up for all the time lost while paused.
ResetThrottle(GetTicks());
}
});
}
void CoreTimingManager::Shutdown()
{
Core::RemoveOnStateChangedCallback(&m_on_state_changed_handle);
std::lock_guard lk(m_ts_write_lock);
MoveEvents();
ClearPendingEvents();
@ -131,6 +141,8 @@ void CoreTimingManager::RefreshConfig()
m_max_variance = std::chrono::duration_cast<DT>(DT_ms(Config::Get(Config::MAIN_TIMING_VARIANCE)));
m_correct_time_drift = Config::Get(Config::MAIN_CORRECT_TIME_DRIFT);
if (AchievementManager::GetInstance().IsHardcoreModeActive() &&
Config::Get(Config::MAIN_EMULATION_SPEED) < 1.0f &&
Config::Get(Config::MAIN_EMULATION_SPEED) > 0.0f)
@ -428,7 +440,9 @@ void CoreTimingManager::Throttle(const s64 target_cycle)
const TimePoint time = Clock::now();
const TimePoint min_target = time - m_max_fallback;
if (target_time < min_target)
// "Correct Time Drift" setting prevents timing relaxing.
if (!m_correct_time_drift && target_time < min_target)
{
// Core is running too slow.. i.e. CPU bottleneck.
const DT adjustment = min_target - target_time;

View File

@ -211,6 +211,7 @@ private:
DT m_max_fallback = {};
DT m_max_variance = {};
bool m_correct_time_drift = false;
double m_emulation_speed = 1.0;
bool IsSpeedUnlimited() const;
@ -225,6 +226,8 @@ private:
std::atomic_bool m_use_precision_timer = false;
Common::PrecisionTimer m_precision_cpu_timer;
Common::PrecisionTimer m_precision_gpu_timer;
int m_on_state_changed_handle;
};
} // namespace CoreTiming

View File

@ -135,9 +135,11 @@ void Analyzer::FindInstructionStarts(const SDSP& dsp, u16 start_addr, u16 end_ad
// If an instruction potentially raises exceptions, mark the following
// instruction as needing to check for exceptions
if (opcode->opcode == 0x00c0 || opcode->opcode == 0x1800 || opcode->opcode == 0x1880 ||
opcode->opcode == 0x1900 || opcode->opcode == 0x1980 || opcode->opcode == 0x2000 ||
opcode->extended)
if (opcode->opcode == 0x00c0 || opcode->opcode == 0x00e0 || opcode->opcode == 0x1600 ||
opcode->opcode == 0x1800 || opcode->opcode == 0x1880 || opcode->opcode == 0x1900 ||
opcode->opcode == 0x1980 || opcode->opcode == 0x1a00 || opcode->opcode == 0x1a80 ||
opcode->opcode == 0x1b00 || opcode->opcode == 0x1b80 || opcode->opcode == 0x2000 ||
opcode->opcode == 0x2800 || opcode->opcode == 0x2c00 || opcode->extended)
{
m_code_flags[static_cast<u16>(addr + opcode->size)] |= CODE_CHECK_EXC;
}

View File

@ -224,11 +224,11 @@ void SDSP::CheckExternalInterrupt()
control_reg &= ~CR_EXTERNAL_INT;
}
void SDSP::CheckExceptions()
bool SDSP::CheckExceptions()
{
// Early out to skip the loop in the common case.
if (exceptions == 0)
return;
return false;
for (int i = 7; i > 0; i--)
{
@ -247,7 +247,7 @@ void SDSP::CheckExceptions()
r.sr &= ~SR_EXT_INT_ENABLE;
else
r.sr &= ~SR_INT_ENABLE;
break;
return true;
}
else
{
@ -257,6 +257,8 @@ void SDSP::CheckExceptions()
}
}
}
return false;
}
u16 SDSP::ReadRegister(size_t reg) const
@ -541,9 +543,9 @@ void DSPCore::CheckExternalInterrupt()
m_dsp.CheckExternalInterrupt();
}
void DSPCore::CheckExceptions()
bool DSPCore::CheckExceptions()
{
m_dsp.CheckExceptions();
return m_dsp.CheckExceptions();
}
u16 DSPCore::ReadRegister(size_t reg) const

View File

@ -383,7 +383,7 @@ struct SDSP
void SetException(ExceptionType exception);
// Checks if any exceptions occurred an updates the DSP state as appropriate.
void CheckExceptions();
bool CheckExceptions();
// Notify that an external interrupt is pending (used by thread mode)
void SetExternalInterrupt(bool val);
@ -530,7 +530,7 @@ public:
void CheckExternalInterrupt();
// Checks if any exceptions occurred an updates the DSP state as appropriate.
void CheckExceptions();
bool CheckExceptions();
// Reads the current value from a particular register.
u16 ReadRegister(size_t reg) const;

View File

@ -99,9 +99,9 @@ void DSPEmitter::ClearIRAMandDSPJITCodespaceReset()
m_dsp_core.DSPState().reset_dspjit_codespace = false;
}
static void CheckExceptionsThunk(DSPCore& dsp)
static u32 CheckExceptionsThunk(DSPCore& dsp)
{
dsp.CheckExceptions();
return dsp.CheckExceptions() ? 1u : 0u;
}
// Must go out of block if exception is detected
@ -116,8 +116,11 @@ void DSPEmitter::checkExceptions(u32 retval)
DSPJitRegCache c(m_gpr);
m_gpr.SaveRegs();
ABI_CallFunctionP(CheckExceptionsThunk, &m_dsp_core);
TEST(32, R(ABI_RETURN), R(ABI_RETURN));
FixupBranch skip_return = J_CC(CC_Z, Jump::Short);
MOV(32, R(EAX), Imm32(retval));
JMP(m_return_dispatcher, Jump::Near);
SetJumpTarget(skip_return);
m_gpr.LoadRegs(false);
m_gpr.FlushRegs(c, false);

View File

@ -132,7 +132,7 @@ class OSThreadView : public Common::Debug::ThreadView
{
public:
explicit OSThreadView(const Core::CPUThreadGuard& guard, u32 addr);
~OSThreadView() = default;
~OSThreadView() override = default;
const OSThread& Data() const;

View File

@ -220,7 +220,7 @@ class FifoPlayer::CPUCore final : public CPUCoreBase
public:
explicit CPUCore(FifoPlayer* parent) : m_parent(parent) {}
CPUCore(const CPUCore&) = delete;
~CPUCore() {}
~CPUCore() override {}
CPUCore& operator=(const CPUCore&) = delete;
void Init() override

View File

@ -157,7 +157,7 @@ class VAListStruct : public VAList
{
public:
explicit VAListStruct(const Core::CPUThreadGuard& guard, u32 address);
~VAListStruct() = default;
~VAListStruct() override = default;
private:
struct svr4_va_list

View File

@ -28,7 +28,7 @@ public:
DSPHLE(DSPHLE&& other) = delete;
DSPHLE& operator=(const DSPHLE& other) = delete;
DSPHLE& operator=(DSPHLE&& other) = delete;
~DSPHLE();
~DSPHLE() override;
bool Initialize(bool wii, bool dsp_thread) override;
void Shutdown() override;

View File

@ -27,7 +27,7 @@ public:
AESndAccelerator(AESndAccelerator&&) = delete;
AESndAccelerator& operator=(const AESndAccelerator&) = delete;
AESndAccelerator& operator=(AESndAccelerator&&) = delete;
~AESndAccelerator();
~AESndAccelerator() override;
protected:
void OnRawReadEndException() override {}

View File

@ -129,7 +129,7 @@ public:
HLEAccelerator(HLEAccelerator&&) = delete;
HLEAccelerator& operator=(const HLEAccelerator&) = delete;
HLEAccelerator& operator=(HLEAccelerator&&) = delete;
~HLEAccelerator() = default;
~HLEAccelerator() override = default;
PB_TYPE* acc_pb = nullptr;

View File

@ -20,7 +20,7 @@ class DSPLLE : public DSPEmulator
{
public:
DSPLLE();
~DSPLLE();
~DSPLLE() override;
bool Initialize(bool wii, bool dsp_thread) override;
void Shutdown() override;

View File

@ -18,7 +18,7 @@ class CEXIAgp : public IEXIDevice
{
public:
CEXIAgp(Core::System& system, const Slot slot);
virtual ~CEXIAgp() override;
~CEXIAgp() override;
bool IsPresent() const override { return true; }
void ImmWrite(u32 _uData, u32 _uSize) override;
u32 ImmRead(u32 _uSize) override;

View File

@ -216,7 +216,7 @@ class CEXIETHERNET : public IEXIDevice
{
public:
CEXIETHERNET(Core::System& system, BBADeviceType type);
virtual ~CEXIETHERNET();
~CEXIETHERNET() override;
void SetCS(int cs) override;
bool IsPresent() const override;
bool IsInterruptSet() override;

View File

@ -18,7 +18,7 @@ class CEXIMic : public IEXIDevice
{
public:
CEXIMic(Core::System& system, const int index);
virtual ~CEXIMic();
~CEXIMic() override;
void SetCS(int cs) override;
bool IsInterruptSet() override;
bool IsPresent() const override;

View File

@ -33,7 +33,7 @@ class CEXIModem : public IEXIDevice
{
public:
CEXIModem(Core::System& system, ModemDeviceType type);
virtual ~CEXIModem();
~CEXIModem() override;
void SetCS(int cs) override;
bool IsPresent() const override;
bool IsInterruptSet() override;
@ -136,13 +136,13 @@ private:
TAPServerNetworkInterface(CEXIModem* modem_ref, const std::string& destination);
public:
virtual bool Activate() override;
virtual void Deactivate() override;
virtual bool IsActivated() override;
virtual bool SendAndRemoveAllHDLCFrames(std::string* send_buffer) override;
virtual bool RecvInit() override;
virtual void RecvStart() override;
virtual void RecvStop() override;
bool Activate() override;
void Deactivate() override;
bool IsActivated() override;
bool SendAndRemoveAllHDLCFrames(std::string* send_buffer) override;
bool RecvInit() override;
void RecvStart() override;
void RecvStop() override;
private:
TAPServerConnection m_tapserver_if;

View File

@ -12,6 +12,10 @@
#include <mgba/core/timing.h>
#include <mgba/internal/gb/gb.h>
#include <mgba/internal/gba/gba.h>
#include <mz.h>
#include <mz_strm.h>
#include <mz_zip.h>
#include <mz_zip_rw.h>
#include "AudioCommon/AudioCommon.h"
#include "Common/ChunkFile.h"
@ -88,21 +92,26 @@ static VFile* OpenROM_Archive(const char* path)
static VFile* OpenROM_Zip(const char* path)
{
VFile* vf{};
unzFile zip = unzOpen(path);
if (!zip)
void* zip_reader = mz_zip_reader_create();
if (!zip_reader)
return {};
Common::ScopeGuard file_guard{[&] { mz_zip_reader_delete(&zip_reader); }};
if (mz_zip_reader_open_file(zip_reader, path) != MZ_OK)
return nullptr;
do
{
unz_file_info info{};
if (unzGetCurrentFileInfo(zip, &info, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK ||
!info.uncompressed_size)
mz_zip_file* info;
if (mz_zip_reader_entry_get_info(zip_reader, &info) != MZ_OK || !info->uncompressed_size)
continue;
std::vector<u8> buffer(info.uncompressed_size);
if (!Common::ReadFileFromZip(zip, &buffer))
std::vector<u8> buffer(info->uncompressed_size);
if (!Common::ReadFileFromZip(zip_reader, &buffer))
continue;
vf = VFileMemChunk(buffer.data(), info.uncompressed_size);
vf = VFileMemChunk(buffer.data(), info->uncompressed_size);
if (mCoreIsCompatible(vf) == mPLATFORM_GBA)
{
vf->seek(vf, 0, SEEK_SET);
@ -111,8 +120,7 @@ static VFile* OpenROM_Zip(const char* path)
vf->close(vf);
vf = nullptr;
} while (unzGoToNextFile(zip) == UNZ_OK);
unzClose(zip);
} while (mz_zip_reader_goto_next_entry(zip_reader) != MZ_END_OF_LIST);
return vf;
}

View File

@ -24,7 +24,7 @@ class GCMemcardDirectory : public MemoryCardBase
public:
GCMemcardDirectory(const std::string& directory, ExpansionInterface::Slot slot,
const Memcard::HeaderData& header_data, u32 game_id);
~GCMemcardDirectory();
~GCMemcardDirectory() override;
GCMemcardDirectory(const GCMemcardDirectory&) = delete;
GCMemcardDirectory& operator=(const GCMemcardDirectory&) = delete;

View File

@ -19,7 +19,7 @@ class MemoryCard : public MemoryCardBase
public:
MemoryCard(const std::string& filename, ExpansionInterface::Slot card_slot,
u16 size_mbits = Memcard::MBIT_SIZE_MEMORY_CARD_2043);
~MemoryCard();
~MemoryCard() override;
void FlushThread();
void MakeDirty();

View File

@ -39,7 +39,7 @@ class ConstantHandlingMethod : public ReadHandlingMethod<T>
{
public:
explicit ConstantHandlingMethod(T value) : value_(value) {}
virtual ~ConstantHandlingMethod() = default;
~ConstantHandlingMethod() override = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitConstant(value_);
@ -62,7 +62,7 @@ class NopHandlingMethod : public WriteHandlingMethod<T>
{
public:
NopHandlingMethod() {}
virtual ~NopHandlingMethod() = default;
~NopHandlingMethod() override = default;
void AcceptWriteVisitor(WriteHandlingMethodVisitor<T>& v) const override { v.VisitNop(); }
};
template <typename T>
@ -79,7 +79,7 @@ class DirectHandlingMethod : public ReadHandlingMethod<T>, public WriteHandlingM
{
public:
DirectHandlingMethod(T* addr, u32 mask) : addr_(addr), mask_(mask) {}
virtual ~DirectHandlingMethod() = default;
~DirectHandlingMethod() override = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitDirect(addr_, mask_);
@ -122,7 +122,7 @@ public:
{
}
virtual ~ComplexHandlingMethod() = default;
~ComplexHandlingMethod() override = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitComplex(&read_lambda_);

View File

@ -21,7 +21,7 @@ class CSIDevice_GBAEmu final : public ISIDevice
{
public:
CSIDevice_GBAEmu(Core::System& system, SIDevices device, int device_number);
~CSIDevice_GBAEmu();
~CSIDevice_GBAEmu() override;
int RunBuffer(u8* buffer, int request_length) override;
int TransferInterval() override;

View File

@ -311,7 +311,7 @@ void EmulateIMUCursor(IMUCursorState* state, ControllerEmu::IMUCursor* imu_ir_gr
const auto ang_vel = imu_gyroscope_group->GetState();
// Reset if pointing is disabled or we have no gyro data.
if (!imu_ir_group->enabled || !ang_vel.has_value())
if (!imu_ir_group->enabled.GetValue() || !ang_vel.has_value())
{
*state = {};
return;

View File

@ -120,7 +120,7 @@ protected:
using EncryptedExtension::EncryptedExtension;
private:
void UpdateEncryptionKey() final override;
void UpdateEncryptionKey() final;
};
class Extension3rdParty : public EncryptedExtension
@ -129,7 +129,7 @@ protected:
using EncryptedExtension::EncryptedExtension;
private:
void UpdateEncryptionKey() final override;
void UpdateEncryptionKey() final;
};
} // namespace WiimoteEmu

View File

@ -497,7 +497,7 @@ void Wiimote::BuildDesiredWiimoteState(DesiredWiimoteState* target_state,
ConvertAccelData(GetTotalAcceleration(), ACCEL_ZERO_G << 2, ACCEL_ONE_G << 2);
// Calculate IR camera state.
if (m_ir_passthrough->enabled)
if (m_ir_passthrough->enabled.GetValue())
{
target_state->camera_points = GetPassthroughCameraPoints(m_ir_passthrough);
}

View File

@ -137,7 +137,7 @@ public:
static constexpr const char* SIDEWAYS_OPTION = "Sideways Wiimote";
explicit Wiimote(unsigned int index);
~Wiimote();
~Wiimote() override;
std::string GetName() const override;

View File

@ -34,7 +34,7 @@ class WiimoteScannerHidapi final : public WiimoteScannerBackend
{
public:
WiimoteScannerHidapi();
~WiimoteScannerHidapi();
~WiimoteScannerHidapi() override;
bool IsReady() const override;
void FindWiimotes(std::vector<Wiimote*>&, Wiimote*&) override;
void Update() override {} // not needed for hidapi

View File

@ -233,7 +233,7 @@ class HotkeyManager : public ControllerEmu::EmulatedController
{
public:
HotkeyManager();
~HotkeyManager();
~HotkeyManager() override;
void GetInput(HotkeyStatus* hk, bool ignore_focus);
std::string GetName() const override;

View File

@ -479,9 +479,7 @@ bool ESDevice::LaunchPPCTitle(u64 title_id)
if (!Core::IsRunning(system))
return BootstrapPPC();
INFO_LOG_FMT(ACHIEVEMENTS,
"WAD and NAND formats not currently supported by Achievement Manager.");
AchievementManager::GetInstance().CloseGame();
AchievementManager::GetInstance().LoadGame(nullptr);
core_timing.RemoveEvent(s_bootstrap_ppc_for_launch_event);
core_timing.ScheduleEvent(ticks, s_bootstrap_ppc_for_launch_event);

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