Compare commits

..

2 Commits

Author SHA1 Message Date
OatmealDome
9843115ad8
ScmRevGen: Bump version to 2506a 2025-06-05 02:52:15 -04:00
JosJuice
a834df67ae
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-05 02:51:47 -04:00
397 changed files with 4022 additions and 8027 deletions

3
.gitmodules vendored
View File

@ -84,9 +84,6 @@
[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

@ -34,7 +34,7 @@ string(TIMESTAMP DOLPHIN_WC_BUILD_DATE "%Y-%m-%d" UTC)
# version number
set(DOLPHIN_VERSION_MAJOR "2506")
set(DOLPHIN_VERSION_MINOR "0")
set(DOLPHIN_VERSION_MINOR "1")
set(DOLPHIN_VERSION_PATCH ${DOLPHIN_WC_REVISION})
# If Dolphin is not built from a Git repository, default the version info to

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-ng
"minizip-ng>=4.0.4" minizip-ng::minizip-ng Externals/minizip-ng
dolphin_find_optional_system_library_pkgconfig(MINIZIP
"minizip>=4.0.4" minizip::minizip Externals/minizip-ng
)
dolphin_find_optional_system_library(LZO Externals/LZO)
@ -784,8 +784,6 @@ 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

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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, SQIY4Q - Disney Infinity
# SQIE4Q, SQIP4Q - Disney Infinity
[Core]
# Values set here will override the main Dolphin settings.

View File

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -1,9 +0,0 @@
# 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

@ -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-ng::minizip-ng ALIAS minizip)
add_library(minizip::minizip ALIAS minizip)

View File

@ -23,6 +23,8 @@
</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" />
@ -37,6 +39,8 @@
</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" />

View File

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

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

View File

@ -1,28 +0,0 @@
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,10 +122,6 @@ 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()
@ -566,21 +562,6 @@ 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" {
@ -817,13 +798,6 @@ 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;
}
@ -860,6 +834,5 @@ 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,8 +121,4 @@ jmethodID GetPermissionHandlerRequestRecordAudioPermission();
jmethodID GetRunnableRun();
jclass GetAudioUtilsClass();
jmethodID GetAudioUtilsGetSampleRate();
jmethodID GetAudioUtilsGetFramesPerBuffer();
} // namespace IDCache

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.GetValue());
return static_cast<jboolean>(GetPointer(env, obj)->enabled);
}
JNIEXPORT void JNICALL
Java_org_dolphinemu_dolphinemu_features_input_model_controlleremu_ControlGroup_setEnabled(
JNIEnv* env, jobject obj, jboolean value)
{
GetPointer(env, obj)->enabled.SetValue(value);
GetPointer(env, obj)->enabled = value;
}
JNIEXPORT jint JNICALL

View File

@ -16,7 +16,6 @@
#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"
@ -167,8 +166,7 @@ void UpdateSoundStream(Core::System& system)
if (sound_stream)
{
int const volume =
Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME);
int volume = Config::Get(Config::MAIN_AUDIO_MUTED) ? 0 : Config::Get(Config::MAIN_AUDIO_VOLUME);
sound_stream->SetVolume(volume);
}
}
@ -194,7 +192,7 @@ void SetSoundStreamRunning(Core::System& system, bool running)
void SendAIBuffer(Core::System& system, const short* samples, unsigned int num_samples)
{
const SoundStream* const sound_stream = system.GetSoundStream();
SoundStream* sound_stream = system.GetSoundStream();
if (!sound_stream)
return;
@ -214,17 +212,14 @@ void SendAIBuffer(Core::System& system, const short* samples, unsigned int num_s
void StartAudioDump(Core::System& system)
{
const SoundStream* const sound_stream = system.GetSoundStream();
SoundStream* sound_stream = system.GetSoundStream();
std::time_t const start_time = std::time(nullptr);
std::time_t start_time = std::time(nullptr);
std::string path_prefix = File::GetUserPath(D_DUMPAUDIO_IDX) + SConfig::GetInstance().GetGameID();
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);
std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, fmt::localtime(start_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);
@ -237,7 +232,7 @@ void StartAudioDump(Core::System& system)
void StopAudioDump(Core::System& system)
{
const SoundStream* const sound_stream = system.GetSoundStream();
SoundStream* sound_stream = system.GetSoundStream();
if (!sound_stream)
return;
@ -270,7 +265,7 @@ void DecreaseVolume(Core::System& system, unsigned short offset)
void ToggleMuteVolume(Core::System& system)
{
bool const isMuted = Config::Get(Config::MAIN_AUDIO_MUTED);
bool isMuted = Config::Get(Config::MAIN_AUDIO_MUTED);
Config::SetBaseOrCurrent(Config::MAIN_AUDIO_MUTED, !isMuted);
UpdateSoundStream(system);
}

View File

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

View File

@ -10,6 +10,7 @@
#include "Common/Event.h"
#include "Common/Logging/Log.h"
#include "Common/ScopeGuard.h"
#include "Common/Thread.h"
#include "Core/Config/MainSettings.h"
#ifdef _WIN32
@ -22,7 +23,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)
{
const auto* const self = static_cast<CubebStream*>(user_data);
auto* self = static_cast<CubebStream*>(user_data);
if (self->m_stereo)
self->m_mixer->Mix(static_cast<short*>(output_buffer), num_frames);
@ -43,7 +44,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 const result = CoInitializeEx(nullptr, COINIT_MULTITHREADED | COINIT_DISABLE_OLE1DDE);
auto 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,6 +3,8 @@
#pragma once
#include <cstddef>
#include <functional>
#include <memory>
#include <vector>

View File

@ -182,8 +182,7 @@ std::size_t Mixer::MixSurround(float* samples, std::size_t num_samples)
memset(samples, 0, num_samples * SURROUND_CHANNELS * sizeof(float));
std::size_t const needed_frames =
m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples);
std::size_t needed_frames = m_surround_decoder.QueryFramesNeededForSurroundOutput(num_samples);
constexpr std::size_t max_samples = 0x8000;
ASSERT_MSG(AUDIO, needed_frames <= max_samples,
@ -191,7 +190,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 const available_frames = Mix(buffer.data(), static_cast<std::size_t>(needed_frames));
std::size_t available_frames = Mix(buffer.data(), static_cast<std::size_t>(needed_frames));
if (available_frames != needed_frames)
{
ERROR_LOG_FMT(AUDIO,
@ -230,7 +229,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 const volume = m_dma_mixer.GetVolume();
auto volume = m_dma_mixer.GetVolume();
m_wave_writer_dsp.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
}
@ -242,7 +241,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 const volume = m_streaming_mixer.GetVolume();
auto volume = m_streaming_mixer.GetVolume();
m_wave_writer_dtk.AddStereoSamplesBE(samples, static_cast<u32>(num_samples),
sample_rate_divisor, volume.first, volume.second);
}
@ -287,8 +286,7 @@ void Mixer::PushSkylanderPortalSamples(const u8* samples, std::size_t num_sample
{
for (std::size_t i = 0; i < num_samples; ++i)
{
s16 const sample =
static_cast<u16>(samples[i * 2 + 1]) << 8 | static_cast<u16>(samples[i * 2]);
s16 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;
}
@ -337,8 +335,7 @@ void Mixer::StartLogDTKAudio(const std::string& filename)
{
if (!m_log_dtk_audio)
{
bool const success =
m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
bool success = m_wave_writer_dtk.Start(filename, m_streaming_mixer.GetInputSampleRateDivisor());
if (success)
{
m_log_dtk_audio = true;
@ -375,7 +372,7 @@ void Mixer::StartLogDSPAudio(const std::string& filename)
{
if (!m_log_dsp_audio)
{
bool const success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
bool success = m_wave_writer_dsp.Start(filename, m_dma_mixer.GetInputSampleRateDivisor());
if (success)
{
m_log_dsp_audio = true;
@ -497,10 +494,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};
std::size_t const head = m_queue_head.load(std::memory_order_acquire);
const std::size_t head = m_queue_head.load(std::memory_order_acquire);
// Check if we run out of space in the circular queue. (rare)
std::size_t const next_head = (head + 1) & GRANULE_QUEUE_MASK;
std::size_t 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,9 +3,11 @@
#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 const err = palGetError();
ALenum err = palGetError();
if (err != AL_NO_ERROR)
{
@ -211,16 +211,16 @@ void OpenALStream::SoundLoop()
{
Common::SetCurrentThreadName("Audio thread - openal");
bool const float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0;
bool const surround_capable = palIsExtensionPresent("AL_EXT_MCFORMATS") || IsCreativeXFi();
bool float32_capable = palIsExtensionPresent("AL_EXT_float32") != 0;
bool 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 const fixed32_capable = IsCreativeXFi();
bool fixed32_capable = IsCreativeXFi();
u32 const frequency = m_mixer->GetSampleRate();
u32 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 const min_frames = frames_per_buffer;
unsigned int min_frames = frames_per_buffer;
if (use_surround)
{
std::array<float, OAL_MAX_FRAMES * SURROUND_CHANNELS> dpl2;
u32 const rendered_frames = static_cast<u32>(m_mixer->MixSurround(dpl2.data(), min_frames));
u32 rendered_frames = static_cast<u32>(m_mixer->MixSurround(dpl2.data(), min_frames));
if (rendered_frames < min_frames)
continue;
@ -351,8 +351,7 @@ void OpenALStream::SoundLoop()
}
else
{
u32 const rendered_frames =
static_cast<u32>(m_mixer->Mix(m_realtime_buffer.data(), min_frames));
u32 rendered_frames = static_cast<u32>(m_mixer->Mix(m_realtime_buffer.data(), min_frames));
if (!rendered_frames)
continue;

View File

@ -7,6 +7,9 @@
#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,27 +8,40 @@
#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"
void OpenSLESStream::BQPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void* context)
{
reinterpret_cast<OpenSLESStream*>(context)->PushSamples(bq);
}
// engine interfaces
static SLObjectItf engineObject;
static SLEngineItf engineEngine;
static SLObjectItf outputMixObject;
void OpenSLESStream::PushSamples(SLAndroidSimpleBufferQueueItf bq)
// 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)
{
ASSERT(bq == m_bq_player_buffer_queue);
ASSERT(bq == bqPlayerBufferQueue);
ASSERT(nullptr == context);
// Render to the fresh 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
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
// Comment from sample code:
// the most likely other result is SL_RESULT_BUFFER_INSUFFICIENT,
@ -38,78 +51,61 @@ void OpenSLESStream::PushSamples(SLAndroidSimpleBufferQueueItf bq)
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(&m_engine_object, 0, nullptr, 0, nullptr, nullptr);
result = slCreateEngine(&engineObject, 0, nullptr, 0, nullptr, nullptr);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_engine_object)->Realize(m_engine_object, SL_BOOLEAN_FALSE);
result = (*engineObject)->Realize(engineObject, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_engine_object)->GetInterface(m_engine_object, SL_IID_ENGINE, &m_engine_engine);
result = (*engineObject)->GetInterface(engineObject, SL_IID_ENGINE, &engineEngine);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_engine_engine)->CreateOutputMix(m_engine_engine, &m_output_mix_object, 0, 0, 0);
result = (*engineEngine)->CreateOutputMix(engineEngine, &outputMixObject, 0, 0, 0);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_output_mix_object)->Realize(m_output_mix_object, SL_BOOLEAN_FALSE);
result = (*outputMixObject)->Realize(outputMixObject, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
SLDataLocator_AndroidSimpleBufferQueue loc_bufq = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, 2};
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};
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};
SLDataSource audioSrc = {&loc_bufq, &format_pcm};
// configure audio sink
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, m_output_mix_object};
SLDataLocator_OutputMix loc_outmix = {SL_DATALOCATOR_OUTPUTMIX, outputMixObject};
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 = (*m_engine_engine)
->CreateAudioPlayer(m_engine_engine, &m_bq_player_object, &audioSrc, &audioSnk, 2,
ids, req);
result =
(*engineEngine)
->CreateAudioPlayer(engineEngine, &bqPlayerObject, &audioSrc, &audioSnk, 2, ids, req);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_bq_player_object)->Realize(m_bq_player_object, SL_BOOLEAN_FALSE);
result = (*bqPlayerObject)->Realize(bqPlayerObject, SL_BOOLEAN_FALSE);
ASSERT(SL_RESULT_SUCCESS == result);
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);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_PLAY, &bqPlayerPlay);
ASSERT(SL_RESULT_SUCCESS == result);
result =
(*m_bq_player_object)->GetInterface(m_bq_player_object, SL_IID_VOLUME, &m_bq_player_volume);
(*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_BUFFERQUEUE, &bqPlayerBufferQueue);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_bq_player_buffer_queue)
->RegisterCallback(m_bq_player_buffer_queue, BQPlayerCallback, this);
result = (*bqPlayerObject)->GetInterface(bqPlayerObject, SL_IID_VOLUME, &bqPlayerVolume);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*m_bq_player_play)->SetPlayState(m_bq_player_play, SL_PLAYSTATE_PLAYING);
result = (*bqPlayerBufferQueue)->RegisterCallback(bqPlayerBufferQueue, bqPlayerCallback, nullptr);
ASSERT(SL_RESULT_SUCCESS == result);
result = (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, SL_PLAYSTATE_PLAYING);
ASSERT(SL_RESULT_SUCCESS == result);
// Render and enqueue a first buffer.
m_current_buffer ^= 1;
curBuffer ^= 1;
g_mixer = m_mixer.get();
result = (*m_bq_player_buffer_queue)
->Enqueue(m_bq_player_buffer_queue, m_buffer[0].data(), m_bytes_per_buffer);
result = (*bqPlayerBufferQueue)->Enqueue(bqPlayerBufferQueue, buffer[0], sizeof(buffer[0]));
if (SL_RESULT_SUCCESS != result)
return false;
@ -118,39 +114,39 @@ bool OpenSLESStream::Init()
OpenSLESStream::~OpenSLESStream()
{
if (m_bq_player_object != nullptr)
if (bqPlayerObject != 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;
(*bqPlayerObject)->Destroy(bqPlayerObject);
bqPlayerObject = nullptr;
bqPlayerPlay = nullptr;
bqPlayerBufferQueue = nullptr;
bqPlayerVolume = nullptr;
}
if (m_output_mix_object != nullptr)
if (outputMixObject != nullptr)
{
(*m_output_mix_object)->Destroy(m_output_mix_object);
m_output_mix_object = nullptr;
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject = nullptr;
}
if (m_engine_object != nullptr)
if (engineObject != nullptr)
{
(*m_engine_object)->Destroy(m_engine_object);
m_engine_object = nullptr;
m_engine_engine = nullptr;
(*engineObject)->Destroy(engineObject);
engineObject = nullptr;
engineEngine = nullptr;
}
}
bool OpenSLESStream::SetRunning(bool running)
{
SLuint32 new_state = running ? SL_PLAYSTATE_PLAYING : SL_PLAYSTATE_PAUSED;
return (*m_bq_player_play)->SetPlayState(m_bq_player_play, new_state) == SL_RESULT_SUCCESS;
return (*bqPlayerPlay)->SetPlayState(bqPlayerPlay, 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));
(*m_bq_player_volume)->SetVolumeLevel(m_bq_player_volume, attenuation);
(*bqPlayerVolume)->SetVolumeLevel(bqPlayerVolume, attenuation);
}
#endif // HAVE_OPENSL_ES

View File

@ -3,15 +3,10 @@
#pragma once
#ifdef HAVE_OPENSL_ES
#include <array>
#include <vector>
#include <SLES/OpenSLES.h>
#include <SLES/OpenSLES_Android.h>
#endif // HAVE_OPENSL_ES
#include <thread>
#include "AudioCommon/SoundStream.h"
#include "Common/Event.h"
class OpenSLESStream final : public SoundStream
{
@ -24,25 +19,7 @@ public:
static bool IsValid() { return true; }
private:
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;
std::thread thread;
Common::Event soundSyncEvent;
#endif // HAVE_OPENSL_ES
};

View File

@ -8,6 +8,7 @@
#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 const frames_needed = output_frames - m_decoded_fifo.size() / SURROUND_CHANNELS;
size_t 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,6 +8,7 @@
// clang-format off
#include <Audioclient.h>
#include <mmdeviceapi.h>
#include <devpkey.h>
#include <functiondiscoverykeys_devpkey.h>
#include <wil/resource.h>
// clang-format on
@ -158,9 +159,8 @@ ComPtr<IMMDevice> WASAPIStream::GetDeviceByName(std::string_view name)
bool WASAPIStream::Init()
{
ASSERT(m_enumerator == nullptr);
HRESULT const result =
CoCreateInstance(__uuidof(MMDeviceEnumerator), nullptr, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(m_enumerator.GetAddressOf()));
HRESULT 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() override;
~WASAPIStream();
bool Init() override;
bool SetRunning(bool running) override;

View File

@ -47,14 +47,14 @@ bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
}
// Check if the file is already open
if (m_file)
if (file)
{
PanicAlertFmtT("The file {0} was already open, the file header will not be written.", filename);
return false;
}
m_file.Open(filename, "wb");
if (!m_file)
file.Open(filename, "wb");
if (!file)
{
PanicAlertFmtT(
"The file {0} could not be opened for writing. Please check if it's already opened "
@ -63,12 +63,12 @@ bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
return false;
}
m_audio_size = 0;
audio_size = 0;
if (m_basename.empty())
SplitPath(filename, nullptr, &m_basename, nullptr);
if (basename.empty())
SplitPath(filename, nullptr, &basename, nullptr);
m_current_sample_rate_divisor = sample_rate_divisor;
current_sample_rate_divisor = sample_rate_divisor;
// -----------------
// Write file header
@ -90,37 +90,37 @@ bool WaveFileWriter::Start(const std::string& filename, u32 sample_rate_divisor)
Write(100 * 1000 * 1000 - 32);
// We are now at offset 44
if (m_file.Tell() != 44)
PanicAlertFmt("Wrong offset: {}", m_file.Tell());
if (file.Tell() != 44)
PanicAlertFmt("Wrong offset: {}", file.Tell());
return true;
}
void WaveFileWriter::Stop()
{
m_file.Seek(4, File::SeekOrigin::Begin);
Write(m_audio_size + 36);
file.Seek(4, File::SeekOrigin::Begin);
Write(audio_size + 36);
m_file.Seek(40, File::SeekOrigin::Begin);
Write(m_audio_size);
file.Seek(40, File::SeekOrigin::Begin);
Write(audio_size);
m_file.Close();
file.Close();
}
void WaveFileWriter::Write(u32 value)
{
m_file.WriteArray(&value, 1);
file.WriteArray(&value, 1);
}
void WaveFileWriter::Write4(const char* ptr)
{
m_file.WriteBytes(ptr, 4);
file.WriteBytes(ptr, 4);
}
void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count,
u32 sample_rate_divisor, int l_volume, int r_volume)
{
if (!m_file)
if (!file)
{
ERROR_LOG_FMT(AUDIO, "WaveFileWriter - file not open.");
return;
@ -132,7 +132,7 @@ void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count,
return;
}
if (m_skip_silence)
if (skip_silence)
{
bool all_zero = true;
@ -149,24 +149,24 @@ void WaveFileWriter::AddStereoSamplesBE(const short* sample_data, u32 count,
for (u32 i = 0; i < count; i++)
{
// Flip the audio channels from RL to LR
m_conv_buffer[2 * i] = Common::swap16((u16)sample_data[2 * i + 1]);
m_conv_buffer[2 * i + 1] = Common::swap16((u16)sample_data[2 * i]);
conv_buffer[2 * i] = Common::swap16((u16)sample_data[2 * i + 1]);
conv_buffer[2 * i + 1] = Common::swap16((u16)sample_data[2 * i]);
// Apply volume (volume ranges from 0 to 256)
m_conv_buffer[2 * i] = m_conv_buffer[2 * i] * l_volume / 256;
m_conv_buffer[2 * i + 1] = m_conv_buffer[2 * i + 1] * r_volume / 256;
conv_buffer[2 * i] = conv_buffer[2 * i] * l_volume / 256;
conv_buffer[2 * i + 1] = conv_buffer[2 * i + 1] * r_volume / 256;
}
if (sample_rate_divisor != m_current_sample_rate_divisor)
if (sample_rate_divisor != current_sample_rate_divisor)
{
Stop();
m_file_index++;
file_index++;
const std::string filename =
fmt::format("{}{}{}.wav", File::GetUserPath(D_DUMPAUDIO_IDX), m_basename, m_file_index);
fmt::format("{}{}{}.wav", File::GetUserPath(D_DUMPAUDIO_IDX), basename, file_index);
Start(filename, sample_rate_divisor);
m_current_sample_rate_divisor = sample_rate_divisor;
current_sample_rate_divisor = sample_rate_divisor;
}
m_file.WriteBytes(m_conv_buffer.data(), count * 4);
m_audio_size += count * 4;
file.WriteBytes(conv_buffer.data(), count * 4);
audio_size += count * 4;
}

View File

@ -33,11 +33,11 @@ public:
bool Start(const std::string& filename, u32 sample_rate_divisor);
void Stop();
void SetSkipSilence(bool skip) { m_skip_silence = skip; }
void SetSkipSilence(bool skip) { skip_silence = skip; }
// big endian
void AddStereoSamplesBE(const short* sample_data, u32 count, u32 sample_rate_divisor,
int l_volume, int r_volume);
u32 GetAudioSize() const { return m_audio_size; }
u32 GetAudioSize() const { return audio_size; }
private:
static constexpr size_t BUFFER_SIZE = 32 * 1024;
@ -45,13 +45,13 @@ private:
void Write(u32 value);
void Write4(const char* ptr);
File::IOFile m_file;
std::string m_basename;
u32 m_file_index = 0;
u32 m_audio_size = 0;
File::IOFile file;
std::string basename;
u32 file_index = 0;
u32 audio_size = 0;
u32 m_current_sample_rate_divisor;
std::array<short, BUFFER_SIZE> m_conv_buffer{};
u32 current_sample_rate_divisor;
std::array<short, BUFFER_SIZE> conv_buffer{};
bool m_skip_silence = false;
bool skip_silence = false;
};

View File

@ -31,7 +31,7 @@ public:
{
m_active_block = &m_output_result.blocks.emplace_back(base_addr);
}
~GekkoIRPlugin() override = default;
virtual ~GekkoIRPlugin() = default;
void OnDirectivePre(GekkoDirective directive) override;
void OnDirectivePost(GekkoDirective directive) override;
@ -504,15 +504,16 @@ void GekkoIRPlugin::AddBinaryEvaluator(u32 (*evaluator)(u32, u32))
m_fixup_stack.pop();
std::function<u32()> lhs = std::move(m_fixup_stack.top());
m_fixup_stack.pop();
m_fixup_stack.emplace(
[evaluator, lhs = std::move(lhs), rhs = std::move(rhs)] { return evaluator(lhs(), rhs()); });
m_fixup_stack.emplace([evaluator, lhs = std::move(lhs), rhs = std::move(rhs)]() {
return evaluator(lhs(), rhs());
});
}
void GekkoIRPlugin::AddUnaryEvaluator(u32 (*evaluator)(u32))
{
std::function<u32()> sub = std::move(m_fixup_stack.top());
m_fixup_stack.pop();
m_fixup_stack.emplace([evaluator, sub = std::move(sub)] { return evaluator(sub()); });
m_fixup_stack.emplace([evaluator, sub = std::move(sub)]() { return evaluator(sub()); });
}
void GekkoIRPlugin::AddAbsoluteAddressConv()
@ -578,7 +579,7 @@ void GekkoIRPlugin::AddNumLabelSymResolve(std::string_view sym, u32 num)
// Searching forward only
size_t search_start_idx = static_cast<size_t>(m_numlabs.size());
m_fixup_stack.emplace(
[this, num, source_address, search_start_idx, err_on_fail = std::move(err_on_fail)] {
[this, num, source_address, search_start_idx, err_on_fail = std::move(err_on_fail)]() {
for (size_t i = search_start_idx; i < m_numlabs.size(); i++)
{
if (num == m_numlabs[i].first)

View File

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

View File

@ -10,7 +10,6 @@
#ifdef _WIN32
#include <windows.h>
#include <SetupAPI.h>
#define strerror_r(err, buf, len) strerror_s(buf, len, err)
@ -92,28 +91,5 @@ std::optional<std::wstring> GetModuleName(void* hInstance)
name.resize(size);
return name;
}
std::wstring GetDeviceProperty(const HDEVINFO& device_info, const PSP_DEVINFO_DATA device_data,
const DEVPROPKEY* requested_property)
{
DWORD required_size = 0;
DEVPROPTYPE device_property_type;
BOOL result;
result = SetupDiGetDeviceProperty(device_info, device_data, requested_property,
&device_property_type, nullptr, 0, &required_size, 0);
if (!result && GetLastError() != ERROR_INSUFFICIENT_BUFFER)
return std::wstring();
std::vector<TCHAR> unicode_buffer(required_size / sizeof(TCHAR));
result = SetupDiGetDeviceProperty(
device_info, device_data, requested_property, &device_property_type,
reinterpret_cast<PBYTE>(unicode_buffer.data()), required_size, nullptr, 0);
if (!result)
return std::wstring();
return std::wstring(unicode_buffer.data());
}
#endif
} // namespace Common

View File

@ -5,12 +5,6 @@
#include <optional>
#include <string>
#ifdef _WIN32
#include <SetupAPI.h>
#include <cfgmgr32.h>
#include <devpropdef.h>
#endif
#include "Common/CommonTypes.h"
#ifndef _WIN32
@ -64,9 +58,5 @@ std::string GetWin32ErrorString(unsigned long error_code);
// Obtains a full path to the specified module.
std::optional<std::wstring> GetModuleName(void* hInstance);
// Obtains a device property and returns it as a wide string.
std::wstring GetDeviceProperty(const HANDLE& device_info, const PSP_DEVINFO_DATA device_data,
const DEVPROPKEY* requested_property);
#endif
} // namespace Common

View File

@ -46,7 +46,8 @@ public:
ASSERT(!mbedtls_aes_setkey_dec(&ctx, key, 128));
}
bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out, size_t len) const override
virtual 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)
@ -205,7 +206,8 @@ public:
_mm_storeu_si128(&((__m128i*)buf_out)[d], block[d]);
}
bool Crypt(const u8* iv, u8* iv_out, const u8* buf_in, u8* buf_out, size_t len) const override
virtual 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() override { mbedtls_sha1_free(&ctx); }
void Update(const u8* msg, size_t len) override
~ContextMbed() { mbedtls_sha1_free(&ctx); }
virtual void Update(const u8* msg, size_t len) override
{
ASSERT(!mbedtls_sha1_update_ret(&ctx, msg, len));
}
Digest Finish() override
virtual Digest Finish() override
{
Digest digest;
ASSERT(!mbedtls_sha1_finish_ret(&ctx, digest.data()));
return digest;
}
bool HwAccelerated() const override { return false; }
virtual bool HwAccelerated() const override { return false; }
private:
mbedtls_sha1_context ctx{};
@ -204,7 +204,7 @@ private:
}
ATTRIBUTE_TARGET("sha")
void ProcessBlock(const u8* msg) override
virtual 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
}
Digest GetDigest() override
virtual Digest GetDigest() override
{
Digest digest;
_mm_storeu_si128((__m128i*)&digest[0], byterev_16B(state[0]));
@ -257,7 +257,7 @@ private:
return digest;
}
bool HwAccelerated() const override { return true; }
virtual bool HwAccelerated() const override { return true; }
std::array<XmmReg, 2> state{};
};

View File

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

View File

@ -1,67 +0,0 @@
// 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

@ -1,47 +0,0 @@
// 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() override;
~GLContextWGL();
bool IsHeadless() const override;
bool IsHeadless() const;
std::unique_ptr<GLContext> CreateSharedContext() override;

View File

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

View File

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

View File

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

View File

@ -122,6 +122,7 @@ 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.
return fmt::format("{:09}", t % 1000000000);
// 3 for %j, 2 for %H, 2 for %M, 2 for %S.
return fmt::format("{:%j%H%M%S}", fmt::localtime(t));
}
} // namespace Common

View File

@ -2,25 +2,23 @@
// 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)
#else
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;
}
#else
std::tm* result = localtime_r(&time, &local_time);
if (result != &local_time)
return std::nullopt;
#endif
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,26 +165,17 @@ 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));
@ -338,12 +329,11 @@ void AchievementManager::DoFrame()
if (!system)
return;
Core::CPUThreadGuard thread_guard(*system);
u32 mem2_size = (system->IsWii()) ? system->GetMemory().GetExRamSizeReal() : 0;
u32 mem2_size = system->GetMemory().GetExRamSizeReal();
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);
if (mem2_size > 0)
system->GetMemory().CopyFromEmu(m_cloned_memory.data() + MEM1_SIZE, MEM2_START, mem2_size);
system->GetMemory().CopyFromEmu(m_cloned_memory.data() + MEM1_SIZE, MEM2_START, mem2_size);
}
#endif // RC_CLIENT_SUPPORTS_RAINTEGRATION
std::lock_guard lg{m_lock};
@ -380,7 +370,7 @@ bool AchievementManager::CanPause()
void AchievementManager::DoIdle()
{
std::thread([this] {
std::thread([this]() {
while (true)
{
Common::SleepCurrentThread(1000);
@ -608,6 +598,11 @@ 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;
@ -741,8 +736,12 @@ 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});
@ -959,7 +958,7 @@ void AchievementManager::LeaderboardEntriesCallback(int result, const char* erro
rc_client_t* client, void* userdata)
{
u32* leaderboard_id = static_cast<u32*>(userdata);
Common::ScopeGuard on_end_scope([&] { delete leaderboard_id; });
Common::ScopeGuard on_end_scope([&]() { delete leaderboard_id; });
if (result != RC_OK)
{
@ -996,30 +995,36 @@ void AchievementManager::LoadGameCallback(int result, const char* error_message,
OSD::Color::RED);
return;
}
auto* game = rc_client_get_game_info(client);
if (result == RC_OK)
if (result == RC_NO_GAME_LOADED && instance.m_dll_found)
{
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;
}
// 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);
}
else
if (result != RC_OK)
{
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});
@ -1372,7 +1377,7 @@ void AchievementManager::FetchBadge(AchievementManager::Badge* badge, u32 badge_
m_image_queue.Push([this, badge, badge_type, function = std::move(function),
callback_data = std::move(callback_data)] {
Common::ScopeGuard on_end_scope([&] {
Common::ScopeGuard on_end_scope([&]() {
if (m_display_welcome_message && badge_type == RC_IMAGE_TYPE_GAME)
DisplayWelcomeMessage();
});

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 = {
0x6D, 0x91, 0xF5, 0xC1, 0xE2, 0x4C, 0xC3, 0x39, 0xF5, 0x7F,
0xEC, 0xA9, 0x8C, 0xA9, 0xBD, 0x61, 0x28, 0x54, 0x11, 0x62};
0xE1, 0x29, 0xD1, 0x33, 0x4D, 0xF2, 0xF8, 0xA8, 0x4E, 0xCA,
0xF6, 0x87, 0xE6, 0xEC, 0xEC, 0xB3, 0x18, 0x69, 0x34, 0x45};
struct LeaderboardEntry
{
@ -160,6 +160,7 @@ 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);
@ -277,6 +278,9 @@ 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,8 +603,6 @@ 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();
@ -637,8 +635,6 @@ 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;
}
@ -665,8 +661,6 @@ 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;
}
@ -674,7 +668,6 @@ 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() override;
~DolReader();
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() override;
~ElfReader();
u32 Read32(int off) const { return base32[off >> 2]; }
// Quick accessors
ElfType GetType() const { return (ElfType)(header->e_type); }

View File

@ -45,7 +45,6 @@ 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,7 +63,6 @@ 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,7 +8,6 @@
#include <cstring>
#include <functional>
#include <mutex>
#include <optional>
#include <queue>
#include <utility>
#include <variant>
@ -35,7 +34,6 @@
#include "Common/ScopeGuard.h"
#include "Common/StringUtil.h"
#include "Common/Thread.h"
#include "Common/TimeUtil.h"
#include "Common/Version.h"
#include "Core/AchievementManager.h"
@ -84,6 +82,7 @@
#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"
@ -506,13 +505,14 @@ static void EmuThread(Core::System& system, std::unique_ptr<BootParameters> boot
Config::Get(Config::MAIN_WII_SD_CARD_ENABLE_FOLDER_SYNC);
if (sync_sd_folder)
{
sync_sd_folder = Common::SyncSDFolderToSDImage([] { return false; }, Core::WantsDeterminism());
sync_sd_folder =
Common::SyncSDFolderToSDImage([]() { return false; }, Core::WantsDeterminism());
}
Common::ScopeGuard sd_folder_sync_guard{[sync_sd_folder] {
if (sync_sd_folder && Config::Get(Config::MAIN_ALLOW_SD_WRITES))
{
const bool sync_ok = Common::SyncSDImageToSDFolder([] { return false; });
const bool sync_ok = Common::SyncSDImageToSDFolder([]() { return false; });
if (!sync_ok)
{
PanicAlertFmtT(
@ -528,6 +528,9 @@ 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(); });
@ -734,17 +737,15 @@ static std::string GenerateScreenshotFolderPath()
return path;
}
static std::optional<std::string> GenerateScreenshotName()
static 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 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);
const std::string base_name =
fmt::format("{}_{:%Y-%m-%d_%H-%M-%S}", path_prefix, fmt::localtime(cur_time));
// First try a filename without any suffixes, if already exists then append increasing numbers
std::string name = fmt::format("{}.png", base_name);
@ -760,9 +761,7 @@ static std::optional<std::string> GenerateScreenshotName()
void SaveScreenShot()
{
const Core::CPUThreadGuard guard(Core::System::GetInstance());
std::optional<std::string> name = GenerateScreenshotName();
if (name)
g_frame_dumper->SaveScreenshot(*name);
g_frame_dumper->SaveScreenshot(GenerateScreenshotName());
}
void SaveScreenShot(std::string_view name)
@ -828,7 +827,7 @@ void RunOnCPUThread(Core::System& system, Common::MoveOnlyFunction<void()> funct
{
// Trigger the event after executing the function.
s_cpu_thread_job_finished.Reset();
system.GetCPU().AddCPUThreadJob([&function] {
system.GetCPU().AddCPUThreadJob([&function]() {
function();
s_cpu_thread_job_finished.Set();
});

View File

@ -105,20 +105,10 @@ 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();
@ -141,8 +131,6 @@ 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)
@ -440,9 +428,7 @@ void CoreTimingManager::Throttle(const s64 target_cycle)
const TimePoint time = Clock::now();
const TimePoint min_target = time - m_max_fallback;
// "Correct Time Drift" setting prevents timing relaxing.
if (!m_correct_time_drift && target_time < min_target)
if (target_time < min_target)
{
// Core is running too slow.. i.e. CPU bottleneck.
const DT adjustment = min_target - target_time;

View File

@ -211,7 +211,6 @@ private:
DT m_max_fallback = {};
DT m_max_variance = {};
bool m_correct_time_drift = false;
double m_emulation_speed = 1.0;
bool IsSpeedUnlimited() const;
@ -226,8 +225,6 @@ 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,11 +135,9 @@ 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 == 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)
if (opcode->opcode == 0x00c0 || opcode->opcode == 0x1800 || opcode->opcode == 0x1880 ||
opcode->opcode == 0x1900 || opcode->opcode == 0x1980 || opcode->opcode == 0x2000 ||
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;
}
bool SDSP::CheckExceptions()
void SDSP::CheckExceptions()
{
// Early out to skip the loop in the common case.
if (exceptions == 0)
return false;
return;
for (int i = 7; i > 0; i--)
{
@ -247,7 +247,7 @@ bool SDSP::CheckExceptions()
r.sr &= ~SR_EXT_INT_ENABLE;
else
r.sr &= ~SR_INT_ENABLE;
return true;
break;
}
else
{
@ -257,8 +257,6 @@ bool SDSP::CheckExceptions()
}
}
}
return false;
}
u16 SDSP::ReadRegister(size_t reg) const
@ -543,9 +541,9 @@ void DSPCore::CheckExternalInterrupt()
m_dsp.CheckExternalInterrupt();
}
bool DSPCore::CheckExceptions()
void DSPCore::CheckExceptions()
{
return m_dsp.CheckExceptions();
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.
bool CheckExceptions();
void 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.
bool CheckExceptions();
void 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 u32 CheckExceptionsThunk(DSPCore& dsp)
static void CheckExceptionsThunk(DSPCore& dsp)
{
return dsp.CheckExceptions() ? 1u : 0u;
dsp.CheckExceptions();
}
// Must go out of block if exception is detected
@ -116,11 +116,8 @@ 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() override = default;
~OSThreadView() = default;
const OSThread& Data() const;

View File

@ -209,7 +209,7 @@ std::unique_ptr<FifoDataFile> FifoDataFile::Load(const std::string& filename, bo
if (!file)
return nullptr;
auto panic_failed_to_read = [] {
auto panic_failed_to_read = []() {
CriticalAlertFmtT("Failed to read DFF file.");
return nullptr;
};

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() override {}
~CPUCore() {}
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() override = default;
~VAListStruct() = 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() override;
~DSPHLE();
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() override;
~AESndAccelerator();
protected:
void OnRawReadEndException() override {}

View File

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

View File

@ -20,7 +20,7 @@ class DSPLLE : public DSPEmulator
{
public:
DSPLLE();
~DSPLLE() override;
~DSPLLE();
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);
~CEXIAgp() override;
virtual ~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);
~CEXIETHERNET() override;
virtual ~CEXIETHERNET();
void SetCS(int cs) override;
bool IsPresent() const override;
bool IsInterruptSet() override;

View File

@ -296,7 +296,7 @@ void CEXIIPL::TransferByte(u8& data)
DEBUG_LOG_FMT(EXPANSIONINTERFACE, "IPL-DEV data {} {:08x} {:02x}",
m_command.is_write() ? "write" : "read", address, data);
auto UartFifoAccess = [&] {
auto UartFifoAccess = [&]() {
if (m_command.is_write())
{
if (data != '\0')

View File

@ -18,7 +18,7 @@ class CEXIMic : public IEXIDevice
{
public:
CEXIMic(Core::System& system, const int index);
~CEXIMic() override;
virtual ~CEXIMic();
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);
~CEXIModem() override;
virtual ~CEXIModem();
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:
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;
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;
private:
TAPServerConnection m_tapserver_if;

View File

@ -12,10 +12,6 @@
#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"
@ -92,26 +88,21 @@ static VFile* OpenROM_Archive(const char* path)
static VFile* OpenROM_Zip(const char* path)
{
VFile* vf{};
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)
unzFile zip = unzOpen(path);
if (!zip)
return nullptr;
do
{
mz_zip_file* info;
if (mz_zip_reader_entry_get_info(zip_reader, &info) != MZ_OK || !info->uncompressed_size)
unz_file_info info{};
if (unzGetCurrentFileInfo(zip, &info, nullptr, 0, nullptr, 0, nullptr, 0) != UNZ_OK ||
!info.uncompressed_size)
continue;
std::vector<u8> buffer(info->uncompressed_size);
if (!Common::ReadFileFromZip(zip_reader, &buffer))
std::vector<u8> buffer(info.uncompressed_size);
if (!Common::ReadFileFromZip(zip, &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);
@ -120,7 +111,8 @@ static VFile* OpenROM_Zip(const char* path)
vf->close(vf);
vf = nullptr;
} while (mz_zip_reader_goto_next_entry(zip_reader) != MZ_END_OF_LIST);
} while (unzGoToNextFile(zip) == UNZ_OK);
unzClose(zip);
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() override;
~GCMemcardDirectory();
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() override;
~MemoryCard();
void FlushThread();
void MakeDirty();

View File

@ -39,7 +39,7 @@ class ConstantHandlingMethod : public ReadHandlingMethod<T>
{
public:
explicit ConstantHandlingMethod(T value) : value_(value) {}
~ConstantHandlingMethod() override = default;
virtual ~ConstantHandlingMethod() = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitConstant(value_);
@ -62,7 +62,7 @@ class NopHandlingMethod : public WriteHandlingMethod<T>
{
public:
NopHandlingMethod() {}
~NopHandlingMethod() override = default;
virtual ~NopHandlingMethod() = 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) {}
~DirectHandlingMethod() override = default;
virtual ~DirectHandlingMethod() = default;
void AcceptReadVisitor(ReadHandlingMethodVisitor<T>& v) const override
{
v.VisitDirect(addr_, mask_);
@ -122,7 +122,7 @@ public:
{
}
~ComplexHandlingMethod() override = default;
virtual ~ComplexHandlingMethod() = 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() override;
~CSIDevice_GBAEmu();
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.GetValue() || !ang_vel.has_value())
if (!imu_ir_group->enabled || !ang_vel.has_value())
{
*state = {};
return;

View File

@ -120,7 +120,7 @@ protected:
using EncryptedExtension::EncryptedExtension;
private:
void UpdateEncryptionKey() final;
void UpdateEncryptionKey() final override;
};
class Extension3rdParty : public EncryptedExtension
@ -129,7 +129,7 @@ protected:
using EncryptedExtension::EncryptedExtension;
private:
void UpdateEncryptionKey() final;
void UpdateEncryptionKey() final override;
};
} // 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.GetValue())
if (m_ir_passthrough->enabled)
{
target_state->camera_points = GetPassthroughCameraPoints(m_ir_passthrough);
}

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