summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt9
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt4
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt2
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt12
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt34
-rw-r--r--src/android/app/src/main/jni/native.cpp21
-rw-r--r--src/android/app/src/main/jni/native.h2
-rw-r--r--src/common/arm64/native_clock.cpp21
-rw-r--r--src/core/hle/service/hid/hid.cpp12
-rw-r--r--src/core/hle/service/sockets/bsd.cpp77
-rw-r--r--src/core/hle/service/sockets/bsd.h2
-rw-r--r--src/yuzu/configuration/shared_translation.cpp1
-rw-r--r--src/yuzu/main.cpp12
-rw-r--r--src/yuzu/uisettings.h4
17 files changed, 130 insertions, 89 deletions
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
index ed8fe6c3f..9ebd6c732 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/NativeLibrary.kt
@@ -252,7 +252,7 @@ object NativeLibrary {
252 252
253 external fun reloadKeys(): Boolean 253 external fun reloadKeys(): Boolean
254 254
255 external fun initializeSystem() 255 external fun initializeSystem(reload: Boolean)
256 256
257 external fun defaultCPUCore(): Int 257 external fun defaultCPUCore(): Int
258 258
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
index 8c053670c..d114bd53d 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/YuzuApplication.kt
@@ -11,6 +11,7 @@ import java.io.File
11import org.yuzu.yuzu_emu.utils.DirectoryInitialization 11import org.yuzu.yuzu_emu.utils.DirectoryInitialization
12import org.yuzu.yuzu_emu.utils.DocumentsTree 12import org.yuzu.yuzu_emu.utils.DocumentsTree
13import org.yuzu.yuzu_emu.utils.GpuDriverHelper 13import org.yuzu.yuzu_emu.utils.GpuDriverHelper
14import org.yuzu.yuzu_emu.utils.Log
14 15
15fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir 16fun Context.getPublicFilesDir(): File = getExternalFilesDir(null) ?: filesDir
16 17
@@ -49,6 +50,7 @@ class YuzuApplication : Application() {
49 DirectoryInitialization.start() 50 DirectoryInitialization.start()
50 GpuDriverHelper.initializeDriverParameters() 51 GpuDriverHelper.initializeDriverParameters()
51 NativeLibrary.logDeviceInfo() 52 NativeLibrary.logDeviceInfo()
53 Log.logDeviceInfo()
52 54
53 createNotificationChannels() 55 createNotificationChannels()
54 } 56 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
index da98d4ef5..054e4b755 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/activities/EmulationActivity.kt
@@ -107,7 +107,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
107 107
108 val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext) 108 val preferences = PreferenceManager.getDefaultSharedPreferences(YuzuApplication.appContext)
109 if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) { 109 if (!preferences.getBoolean(Settings.PREF_MEMORY_WARNING_SHOWN, false)) {
110 if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.Gb)) { 110 if (MemoryUtil.isLessThan(MemoryUtil.REQUIRED_MEMORY, MemoryUtil.totalMemory)) {
111 Toast.makeText( 111 Toast.makeText(
112 this, 112 this,
113 getString( 113 getString(
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 07bd78bf7..c456c0592 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -312,6 +312,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
312 ViewUtils.showView(binding.surfaceInputOverlay) 312 ViewUtils.showView(binding.surfaceInputOverlay)
313 ViewUtils.hideView(binding.loadingIndicator) 313 ViewUtils.hideView(binding.loadingIndicator)
314 314
315 emulationState.updateSurface()
316
315 // Setup overlay 317 // Setup overlay
316 updateShowFpsOverlay() 318 updateShowFpsOverlay()
317 } 319 }
@@ -805,6 +807,13 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
805 } 807 }
806 808
807 @Synchronized 809 @Synchronized
810 fun updateSurface() {
811 if (surface != null) {
812 NativeLibrary.surfaceChanged(surface)
813 }
814 }
815
816 @Synchronized
808 fun clearSurface() { 817 fun clearSurface() {
809 if (surface == null) { 818 if (surface == null) {
810 Log.warning("[EmulationFragment] clearSurface called, but surface already null.") 819 Log.warning("[EmulationFragment] clearSurface called, but surface already null.")
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
index ba1177426..211b7cf69 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/ui/main/MainActivity.kt
@@ -403,7 +403,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
403 } else { 403 } else {
404 firmwarePath.deleteRecursively() 404 firmwarePath.deleteRecursively()
405 cacheFirmwareDir.copyRecursively(firmwarePath, true) 405 cacheFirmwareDir.copyRecursively(firmwarePath, true)
406 NativeLibrary.initializeSystem() 406 NativeLibrary.initializeSystem(true)
407 getString(R.string.save_file_imported_success) 407 getString(R.string.save_file_imported_success)
408 } 408 }
409 } catch (e: Exception) { 409 } catch (e: Exception) {
@@ -649,7 +649,7 @@ class MainActivity : AppCompatActivity(), ThemeProvider {
649 } 649 }
650 650
651 // Reinitialize relevant data 651 // Reinitialize relevant data
652 NativeLibrary.initializeSystem() 652 NativeLibrary.initializeSystem(true)
653 gamesViewModel.reloadGames(false) 653 gamesViewModel.reloadGames(false)
654 654
655 return@newInstance getString(R.string.user_data_import_success) 655 return@newInstance getString(R.string.user_data_import_success)
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
index 79a07f7ef..5e9a1176a 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/DirectoryInitialization.kt
@@ -15,7 +15,7 @@ object DirectoryInitialization {
15 fun start() { 15 fun start() {
16 if (!areDirectoriesReady) { 16 if (!areDirectoriesReady) {
17 initializeInternalStorage() 17 initializeInternalStorage()
18 NativeLibrary.initializeSystem() 18 NativeLibrary.initializeSystem(false)
19 areDirectoriesReady = true 19 areDirectoriesReady = true
20 } 20 }
21 } 21 }
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt
index fb682c344..aebe84b0f 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/Log.kt
@@ -3,6 +3,8 @@
3 3
4package org.yuzu.yuzu_emu.utils 4package org.yuzu.yuzu_emu.utils
5 5
6import android.os.Build
7
6object Log { 8object Log {
7 // Tracks whether we should share the old log or the current log 9 // Tracks whether we should share the old log or the current log
8 var gameLaunched = false 10 var gameLaunched = false
@@ -16,4 +18,14 @@ object Log {
16 external fun error(message: String) 18 external fun error(message: String)
17 19
18 external fun critical(message: String) 20 external fun critical(message: String)
21
22 fun logDeviceInfo() {
23 info("Device Manufacturer - ${Build.MANUFACTURER}")
24 info("Device Model - ${Build.MODEL}")
25 if (Build.VERSION.SDK_INT > Build.VERSION_CODES.R) {
26 info("SoC Manufacturer - ${Build.SOC_MANUFACTURER}")
27 info("SoC Model - ${Build.SOC_MODEL}")
28 }
29 info("Total System Memory - ${MemoryUtil.getDeviceRAM()}")
30 }
19} 31}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt
index aa4a5539a..9076a86c4 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/utils/MemoryUtil.kt
@@ -27,7 +27,7 @@ object MemoryUtil {
27 const val Pb = Tb * 1024 27 const val Pb = Tb * 1024
28 const val Eb = Pb * 1024 28 const val Eb = Pb * 1024
29 29
30 private fun bytesToSizeUnit(size: Float): String = 30 private fun bytesToSizeUnit(size: Float, roundUp: Boolean = false): String =
31 when { 31 when {
32 size < Kb -> { 32 size < Kb -> {
33 context.getString( 33 context.getString(
@@ -39,63 +39,59 @@ object MemoryUtil {
39 size < Mb -> { 39 size < Mb -> {
40 context.getString( 40 context.getString(
41 R.string.memory_formatted, 41 R.string.memory_formatted,
42 (size / Kb).hundredths, 42 if (roundUp) ceil(size / Kb) else (size / Kb).hundredths,
43 context.getString(R.string.memory_kilobyte) 43 context.getString(R.string.memory_kilobyte)
44 ) 44 )
45 } 45 }
46 size < Gb -> { 46 size < Gb -> {
47 context.getString( 47 context.getString(
48 R.string.memory_formatted, 48 R.string.memory_formatted,
49 (size / Mb).hundredths, 49 if (roundUp) ceil(size / Mb) else (size / Mb).hundredths,
50 context.getString(R.string.memory_megabyte) 50 context.getString(R.string.memory_megabyte)
51 ) 51 )
52 } 52 }
53 size < Tb -> { 53 size < Tb -> {
54 context.getString( 54 context.getString(
55 R.string.memory_formatted, 55 R.string.memory_formatted,
56 (size / Gb).hundredths, 56 if (roundUp) ceil(size / Gb) else (size / Gb).hundredths,
57 context.getString(R.string.memory_gigabyte) 57 context.getString(R.string.memory_gigabyte)
58 ) 58 )
59 } 59 }
60 size < Pb -> { 60 size < Pb -> {
61 context.getString( 61 context.getString(
62 R.string.memory_formatted, 62 R.string.memory_formatted,
63 (size / Tb).hundredths, 63 if (roundUp) ceil(size / Tb) else (size / Tb).hundredths,
64 context.getString(R.string.memory_terabyte) 64 context.getString(R.string.memory_terabyte)
65 ) 65 )
66 } 66 }
67 size < Eb -> { 67 size < Eb -> {
68 context.getString( 68 context.getString(
69 R.string.memory_formatted, 69 R.string.memory_formatted,
70 (size / Pb).hundredths, 70 if (roundUp) ceil(size / Pb) else (size / Pb).hundredths,
71 context.getString(R.string.memory_petabyte) 71 context.getString(R.string.memory_petabyte)
72 ) 72 )
73 } 73 }
74 else -> { 74 else -> {
75 context.getString( 75 context.getString(
76 R.string.memory_formatted, 76 R.string.memory_formatted,
77 (size / Eb).hundredths, 77 if (roundUp) ceil(size / Eb) else (size / Eb).hundredths,
78 context.getString(R.string.memory_exabyte) 78 context.getString(R.string.memory_exabyte)
79 ) 79 )
80 } 80 }
81 } 81 }
82 82
83 // Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for 83 val totalMemory: Float
84 // the potential error created by memInfo.totalMem
85 private val totalMemory: Float
86 get() { 84 get() {
87 val memInfo = ActivityManager.MemoryInfo() 85 val memInfo = ActivityManager.MemoryInfo()
88 with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) { 86 with(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager) {
89 getMemoryInfo(memInfo) 87 getMemoryInfo(memInfo)
90 } 88 }
91 89
92 return ceil( 90 return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) {
93 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) { 91 memInfo.advertisedMem.toFloat()
94 memInfo.advertisedMem.toFloat() 92 } else {
95 } else { 93 memInfo.totalMem.toFloat()
96 memInfo.totalMem.toFloat() 94 }
97 }
98 )
99 } 95 }
100 96
101 fun isLessThan(minimum: Int, size: Float): Boolean = 97 fun isLessThan(minimum: Int, size: Float): Boolean =
@@ -109,5 +105,7 @@ object MemoryUtil {
109 else -> totalMemory < Kb && totalMemory < minimum 105 else -> totalMemory < Kb && totalMemory < minimum
110 } 106 }
111 107
112 fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory) 108 // Devices are unlikely to have 0.5GB increments of memory so we'll just round up to account for
109 // the potential error created by memInfo.totalMem
110 fun getDeviceRAM(): String = bytesToSizeUnit(totalMemory, true)
113} 111}
diff --git a/src/android/app/src/main/jni/native.cpp b/src/android/app/src/main/jni/native.cpp
index 294e41045..46438906e 100644
--- a/src/android/app/src/main/jni/native.cpp
+++ b/src/android/app/src/main/jni/native.cpp
@@ -247,11 +247,13 @@ void EmulationSession::ConfigureFilesystemProvider(const std::string& filepath)
247 } 247 }
248} 248}
249 249
250void EmulationSession::InitializeSystem() { 250void EmulationSession::InitializeSystem(bool reload) {
251 // Initialize logging system 251 if (!reload) {
252 Common::Log::Initialize(); 252 // Initialize logging system
253 Common::Log::SetColorConsoleBackendEnabled(true); 253 Common::Log::Initialize();
254 Common::Log::Start(); 254 Common::Log::SetColorConsoleBackendEnabled(true);
255 Common::Log::Start();
256 }
255 257
256 // Initialize filesystem. 258 // Initialize filesystem.
257 m_system.SetFilesystem(m_vfs); 259 m_system.SetFilesystem(m_vfs);
@@ -667,12 +669,15 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_onTouchReleased(JNIEnv* env, jclass c
667 } 669 }
668} 670}
669 671
670void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz) { 672void Java_org_yuzu_yuzu_1emu_NativeLibrary_initializeSystem(JNIEnv* env, jclass clazz,
673 jboolean reload) {
671 // Create the default config.ini. 674 // Create the default config.ini.
672 Config{}; 675 Config{};
673 // Initialize the emulated system. 676 // Initialize the emulated system.
674 EmulationSession::GetInstance().System().Initialize(); 677 if (!reload) {
675 EmulationSession::GetInstance().InitializeSystem(); 678 EmulationSession::GetInstance().System().Initialize();
679 }
680 EmulationSession::GetInstance().InitializeSystem(reload);
676} 681}
677 682
678jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass clazz) { 683jint Java_org_yuzu_yuzu_1emu_NativeLibrary_defaultCPUCore(JNIEnv* env, jclass clazz) {
diff --git a/src/android/app/src/main/jni/native.h b/src/android/app/src/main/jni/native.h
index 0aa2b085b..3b9596459 100644
--- a/src/android/app/src/main/jni/native.h
+++ b/src/android/app/src/main/jni/native.h
@@ -43,7 +43,7 @@ public:
43 43
44 const Core::PerfStatsResults& PerfStats() const; 44 const Core::PerfStatsResults& PerfStats() const;
45 void ConfigureFilesystemProvider(const std::string& filepath); 45 void ConfigureFilesystemProvider(const std::string& filepath);
46 void InitializeSystem(); 46 void InitializeSystem(bool reload);
47 Core::SystemResultStatus InitializeEmulation(const std::string& filepath); 47 Core::SystemResultStatus InitializeEmulation(const std::string& filepath);
48 48
49 bool IsHandheldOnly(); 49 bool IsHandheldOnly();
diff --git a/src/common/arm64/native_clock.cpp b/src/common/arm64/native_clock.cpp
index 88fdba527..f437d7187 100644
--- a/src/common/arm64/native_clock.cpp
+++ b/src/common/arm64/native_clock.cpp
@@ -1,6 +1,9 @@
1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#ifdef ANDROID
5#include <sys/system_properties.h>
6#endif
4#include "common/arm64/native_clock.h" 7#include "common/arm64/native_clock.h"
5 8
6namespace Common::Arm64 { 9namespace Common::Arm64 {
@@ -65,7 +68,23 @@ bool NativeClock::IsNative() const {
65 68
66u64 NativeClock::GetHostCNTFRQ() { 69u64 NativeClock::GetHostCNTFRQ() {
67 u64 cntfrq_el0 = 0; 70 u64 cntfrq_el0 = 0;
68 asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0)); 71 std::string_view board{""};
72#ifdef ANDROID
73 char buffer[PROP_VALUE_MAX];
74 int len{__system_property_get("ro.product.board", buffer)};
75 board = std::string_view(buffer, static_cast<size_t>(len));
76#endif
77 if (board == "s5e9925") { // Exynos 2200
78 cntfrq_el0 = 25600000;
79 } else if (board == "exynos2100") { // Exynos 2100
80 cntfrq_el0 = 26000000;
81 } else if (board == "exynos9810") { // Exynos 9810
82 cntfrq_el0 = 26000000;
83 } else if (board == "s5e8825") { // Exynos 1280
84 cntfrq_el0 = 26000000;
85 } else {
86 asm("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
87 }
69 return cntfrq_el0; 88 return cntfrq_el0;
70} 89}
71 90
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 929dd5f03..1d4101be9 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1353,7 +1353,7 @@ void Hid::IsUnintendedHomeButtonInputProtectionEnabled(HLERequestContext& ctx) {
1353void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) { 1353void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1354 IPC::RequestParser rp{ctx}; 1354 IPC::RequestParser rp{ctx};
1355 struct Parameters { 1355 struct Parameters {
1356 bool unintended_home_button_input_protection; 1356 bool is_enabled;
1357 INSERT_PADDING_BYTES_NOINIT(3); 1357 INSERT_PADDING_BYTES_NOINIT(3);
1358 Core::HID::NpadIdType npad_id; 1358 Core::HID::NpadIdType npad_id;
1359 u64 applet_resource_user_id; 1359 u64 applet_resource_user_id;
@@ -1364,13 +1364,11 @@ void Hid::EnableUnintendedHomeButtonInputProtection(HLERequestContext& ctx) {
1364 1364
1365 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad); 1365 auto& controller = GetAppletResource()->GetController<Controller_NPad>(HidController::NPad);
1366 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled( 1366 const auto result = controller.SetUnintendedHomeButtonInputProtectionEnabled(
1367 parameters.unintended_home_button_input_protection, parameters.npad_id); 1367 parameters.is_enabled, parameters.npad_id);
1368 1368
1369 LOG_WARNING(Service_HID, 1369 LOG_DEBUG(Service_HID,
1370 "(STUBBED) called, unintended_home_button_input_protection={}, npad_id={}," 1370 "(STUBBED) called, is_enabled={}, npad_id={}, applet_resource_user_id={}",
1371 "applet_resource_user_id={}", 1371 parameters.is_enabled, parameters.npad_id, parameters.applet_resource_user_id);
1372 parameters.unintended_home_button_input_protection, parameters.npad_id,
1373 parameters.applet_resource_user_id);
1374 1372
1375 IPC::ResponseBuilder rb{ctx, 2}; 1373 IPC::ResponseBuilder rb{ctx, 2};
1376 rb.Push(result); 1374 rb.Push(result);
diff --git a/src/core/hle/service/sockets/bsd.cpp b/src/core/hle/service/sockets/bsd.cpp
index 85849d5f3..dd652ca42 100644
--- a/src/core/hle/service/sockets/bsd.cpp
+++ b/src/core/hle/service/sockets/bsd.cpp
@@ -39,6 +39,18 @@ bool IsConnectionBased(Type type) {
39 } 39 }
40} 40}
41 41
42template <typename T>
43T GetValue(std::span<const u8> buffer) {
44 T t{};
45 std::memcpy(&t, buffer.data(), std::min(sizeof(T), buffer.size()));
46 return t;
47}
48
49template <typename T>
50void PutValue(std::span<u8> buffer, const T& t) {
51 std::memcpy(buffer.data(), &t, std::min(sizeof(T), buffer.size()));
52}
53
42} // Anonymous namespace 54} // Anonymous namespace
43 55
44void BSD::PollWork::Execute(BSD* bsd) { 56void BSD::PollWork::Execute(BSD* bsd) {
@@ -316,22 +328,12 @@ void BSD::SetSockOpt(HLERequestContext& ctx) {
316 const s32 fd = rp.Pop<s32>(); 328 const s32 fd = rp.Pop<s32>();
317 const u32 level = rp.Pop<u32>(); 329 const u32 level = rp.Pop<u32>();
318 const OptName optname = static_cast<OptName>(rp.Pop<u32>()); 330 const OptName optname = static_cast<OptName>(rp.Pop<u32>());
319 331 const auto optval = ctx.ReadBuffer();
320 const auto buffer = ctx.ReadBuffer();
321 const u8* optval = buffer.empty() ? nullptr : buffer.data();
322 size_t optlen = buffer.size();
323
324 std::array<u64, 2> values;
325 if ((optname == OptName::SNDTIMEO || optname == OptName::RCVTIMEO) && buffer.size() == 8) {
326 std::memcpy(values.data(), buffer.data(), sizeof(values));
327 optlen = sizeof(values);
328 optval = reinterpret_cast<const u8*>(values.data());
329 }
330 332
331 LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level, 333 LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
332 static_cast<u32>(optname), optlen); 334 static_cast<u32>(optname), optval.size());
333 335
334 BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optlen, optval)); 336 BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
335} 337}
336 338
337void BSD::Shutdown(HLERequestContext& ctx) { 339void BSD::Shutdown(HLERequestContext& ctx) {
@@ -521,18 +523,19 @@ std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protoco
521 523
522std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer, 524std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
523 s32 nfds, s32 timeout) { 525 s32 nfds, s32 timeout) {
524 if (write_buffer.size() < nfds * sizeof(PollFD)) { 526 if (nfds <= 0) {
525 return {-1, Errno::INVAL};
526 }
527
528 if (nfds == 0) {
529 // When no entries are provided, -1 is returned with errno zero 527 // When no entries are provided, -1 is returned with errno zero
530 return {-1, Errno::SUCCESS}; 528 return {-1, Errno::SUCCESS};
531 } 529 }
530 if (read_buffer.size() < nfds * sizeof(PollFD)) {
531 return {-1, Errno::INVAL};
532 }
533 if (write_buffer.size() < nfds * sizeof(PollFD)) {
534 return {-1, Errno::INVAL};
535 }
532 536
533 const size_t length = std::min(read_buffer.size(), write_buffer.size());
534 std::vector<PollFD> fds(nfds); 537 std::vector<PollFD> fds(nfds);
535 std::memcpy(fds.data(), read_buffer.data(), length); 538 std::memcpy(fds.data(), read_buffer.data(), nfds * sizeof(PollFD));
536 539
537 if (timeout >= 0) { 540 if (timeout >= 0) {
538 const s64 seconds = timeout / 1000; 541 const s64 seconds = timeout / 1000;
@@ -580,7 +583,7 @@ std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<con
580 for (size_t i = 0; i < num; ++i) { 583 for (size_t i = 0; i < num; ++i) {
581 fds[i].revents = Translate(host_pollfds[i].revents); 584 fds[i].revents = Translate(host_pollfds[i].revents);
582 } 585 }
583 std::memcpy(write_buffer.data(), fds.data(), length); 586 std::memcpy(write_buffer.data(), fds.data(), nfds * sizeof(PollFD));
584 587
585 return Translate(result); 588 return Translate(result);
586} 589}
@@ -608,8 +611,7 @@ std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
608 new_descriptor.is_connection_based = descriptor.is_connection_based; 611 new_descriptor.is_connection_based = descriptor.is_connection_based;
609 612
610 const SockAddrIn guest_addr_in = Translate(result.sockaddr_in); 613 const SockAddrIn guest_addr_in = Translate(result.sockaddr_in);
611 const size_t length = std::min(sizeof(guest_addr_in), write_buffer.size()); 614 PutValue(write_buffer, guest_addr_in);
612 std::memcpy(write_buffer.data(), &guest_addr_in, length);
613 615
614 return {new_fd, Errno::SUCCESS}; 616 return {new_fd, Errno::SUCCESS};
615} 617}
@@ -619,8 +621,7 @@ Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
619 return Errno::BADF; 621 return Errno::BADF;
620 } 622 }
621 ASSERT(addr.size() == sizeof(SockAddrIn)); 623 ASSERT(addr.size() == sizeof(SockAddrIn));
622 SockAddrIn addr_in; 624 auto addr_in = GetValue<SockAddrIn>(addr);
623 std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
624 625
625 return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in))); 626 return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
626} 627}
@@ -631,8 +632,7 @@ Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
631 } 632 }
632 633
633 UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn)); 634 UNIMPLEMENTED_IF(addr.size() != sizeof(SockAddrIn));
634 SockAddrIn addr_in; 635 auto addr_in = GetValue<SockAddrIn>(addr);
635 std::memcpy(&addr_in, addr.data(), sizeof(addr_in));
636 636
637 return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in))); 637 return Translate(file_descriptors[fd]->socket->Connect(Translate(addr_in)));
638} 638}
@@ -650,7 +650,7 @@ Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
650 650
651 ASSERT(write_buffer.size() >= sizeof(guest_addrin)); 651 ASSERT(write_buffer.size() >= sizeof(guest_addrin));
652 write_buffer.resize(sizeof(guest_addrin)); 652 write_buffer.resize(sizeof(guest_addrin));
653 std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); 653 PutValue(write_buffer, guest_addrin);
654 return Translate(bsd_errno); 654 return Translate(bsd_errno);
655} 655}
656 656
@@ -667,7 +667,7 @@ Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
667 667
668 ASSERT(write_buffer.size() >= sizeof(guest_addrin)); 668 ASSERT(write_buffer.size() >= sizeof(guest_addrin));
669 write_buffer.resize(sizeof(guest_addrin)); 669 write_buffer.resize(sizeof(guest_addrin));
670 std::memcpy(write_buffer.data(), &guest_addrin, sizeof(guest_addrin)); 670 PutValue(write_buffer, guest_addrin);
671 return Translate(bsd_errno); 671 return Translate(bsd_errno);
672} 672}
673 673
@@ -725,7 +725,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
725 optval.size() == sizeof(Errno), { return Errno::INVAL; }, 725 optval.size() == sizeof(Errno), { return Errno::INVAL; },
726 "Incorrect getsockopt option size"); 726 "Incorrect getsockopt option size");
727 optval.resize(sizeof(Errno)); 727 optval.resize(sizeof(Errno));
728 memcpy(optval.data(), &translated_pending_err, sizeof(Errno)); 728 PutValue(optval, translated_pending_err);
729 } 729 }
730 return Translate(getsockopt_err); 730 return Translate(getsockopt_err);
731 } 731 }
@@ -735,7 +735,7 @@ Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& o
735 } 735 }
736} 736}
737 737
738Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval) { 738Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) {
739 if (!IsFileDescriptorValid(fd)) { 739 if (!IsFileDescriptorValid(fd)) {
740 return Errno::BADF; 740 return Errno::BADF;
741 } 741 }
@@ -748,17 +748,15 @@ Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, con
748 Network::SocketBase* const socket = file_descriptors[fd]->socket.get(); 748 Network::SocketBase* const socket = file_descriptors[fd]->socket.get();
749 749
750 if (optname == OptName::LINGER) { 750 if (optname == OptName::LINGER) {
751 ASSERT(optlen == sizeof(Linger)); 751 ASSERT(optval.size() == sizeof(Linger));
752 Linger linger; 752 auto linger = GetValue<Linger>(optval);
753 std::memcpy(&linger, optval, sizeof(linger));
754 ASSERT(linger.onoff == 0 || linger.onoff == 1); 753 ASSERT(linger.onoff == 0 || linger.onoff == 1);
755 754
756 return Translate(socket->SetLinger(linger.onoff != 0, linger.linger)); 755 return Translate(socket->SetLinger(linger.onoff != 0, linger.linger));
757 } 756 }
758 757
759 ASSERT(optlen == sizeof(u32)); 758 ASSERT(optval.size() == sizeof(u32));
760 u32 value; 759 auto value = GetValue<u32>(optval);
761 std::memcpy(&value, optval, sizeof(value));
762 760
763 switch (optname) { 761 switch (optname) {
764 case OptName::REUSEADDR: 762 case OptName::REUSEADDR:
@@ -862,7 +860,7 @@ std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& mess
862 } else { 860 } else {
863 ASSERT(addr.size() == sizeof(SockAddrIn)); 861 ASSERT(addr.size() == sizeof(SockAddrIn));
864 const SockAddrIn result = Translate(addr_in); 862 const SockAddrIn result = Translate(addr_in);
865 std::memcpy(addr.data(), &result, sizeof(result)); 863 PutValue(addr, result);
866 } 864 }
867 } 865 }
868 866
@@ -886,8 +884,7 @@ std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> mes
886 Network::SockAddrIn* p_addr_in = nullptr; 884 Network::SockAddrIn* p_addr_in = nullptr;
887 if (!addr.empty()) { 885 if (!addr.empty()) {
888 ASSERT(addr.size() == sizeof(SockAddrIn)); 886 ASSERT(addr.size() == sizeof(SockAddrIn));
889 SockAddrIn guest_addr_in; 887 auto guest_addr_in = GetValue<SockAddrIn>(addr);
890 std::memcpy(&guest_addr_in, addr.data(), sizeof(guest_addr_in));
891 addr_in = Translate(guest_addr_in); 888 addr_in = Translate(guest_addr_in);
892 p_addr_in = &addr_in; 889 p_addr_in = &addr_in;
893 } 890 }
diff --git a/src/core/hle/service/sockets/bsd.h b/src/core/hle/service/sockets/bsd.h
index 161f22b9b..4f69d382c 100644
--- a/src/core/hle/service/sockets/bsd.h
+++ b/src/core/hle/service/sockets/bsd.h
@@ -163,7 +163,7 @@ private:
163 Errno ListenImpl(s32 fd, s32 backlog); 163 Errno ListenImpl(s32 fd, s32 backlog);
164 std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg); 164 std::pair<s32, Errno> FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg);
165 Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval); 165 Errno GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval);
166 Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, size_t optlen, const void* optval); 166 Errno SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval);
167 Errno ShutdownImpl(s32 fd, s32 how); 167 Errno ShutdownImpl(s32 fd, s32 how);
168 std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message); 168 std::pair<s32, Errno> RecvImpl(s32 fd, u32 flags, std::vector<u8>& message);
169 std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message, 169 std::pair<s32, Errno> RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
diff --git a/src/yuzu/configuration/shared_translation.cpp b/src/yuzu/configuration/shared_translation.cpp
index 3fe448f27..1434b1a56 100644
--- a/src/yuzu/configuration/shared_translation.cpp
+++ b/src/yuzu/configuration/shared_translation.cpp
@@ -156,7 +156,6 @@ std::unique_ptr<TranslationMap> InitializeTranslations(QWidget* parent) {
156 // Ui General 156 // Ui General
157 INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", ""); 157 INSERT(UISettings, select_user_on_boot, "Prompt for user on game boot", "");
158 INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", ""); 158 INSERT(UISettings, pause_when_in_background, "Pause emulation when in background", "");
159 INSERT(UISettings, confirm_before_closing, "Confirm exit while emulation is running", "");
160 INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", ""); 159 INSERT(UISettings, confirm_before_stopping, "Confirm before stopping emulation", "");
161 INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", ""); 160 INSERT(UISettings, hide_mouse, "Hide mouse on inactivity", "");
162 INSERT(UISettings, controller_applet_disabled, "Disable controller applet", ""); 161 INSERT(UISettings, controller_applet_disabled, "Disable controller applet", "");
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index db9da6dc8..91aba118a 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2174,6 +2174,7 @@ void GMainWindow::ShutdownGame() {
2174 return; 2174 return;
2175 } 2175 }
2176 2176
2177 play_time_manager->Stop();
2177 OnShutdownBegin(); 2178 OnShutdownBegin();
2178 OnEmulationStopTimeExpired(); 2179 OnEmulationStopTimeExpired();
2179 OnEmulationStopped(); 2180 OnEmulationStopped();
@@ -3484,7 +3485,7 @@ void GMainWindow::OnExecuteProgram(std::size_t program_index) {
3484} 3485}
3485 3486
3486void GMainWindow::OnExit() { 3487void GMainWindow::OnExit() {
3487 OnStopGame(); 3488 ShutdownGame();
3488} 3489}
3489 3490
3490void GMainWindow::OnSaveConfig() { 3491void GMainWindow::OnSaveConfig() {
@@ -4847,7 +4848,12 @@ bool GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installe
4847} 4848}
4848 4849
4849bool GMainWindow::ConfirmClose() { 4850bool GMainWindow::ConfirmClose() {
4850 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { 4851 if (emu_thread == nullptr ||
4852 UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Never) {
4853 return true;
4854 }
4855 if (!system->GetExitLocked() &&
4856 UISettings::values.confirm_before_stopping.GetValue() == ConfirmStop::Ask_Based_On_Game) {
4851 return true; 4857 return true;
4852 } 4858 }
4853 const auto text = tr("Are you sure you want to close yuzu?"); 4859 const auto text = tr("Are you sure you want to close yuzu?");
@@ -4952,7 +4958,7 @@ bool GMainWindow::ConfirmChangeGame() {
4952} 4958}
4953 4959
4954bool GMainWindow::ConfirmForceLockedExit() { 4960bool GMainWindow::ConfirmForceLockedExit() {
4955 if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { 4961 if (emu_thread == nullptr) {
4956 return true; 4962 return true;
4957 } 4963 }
4958 const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" 4964 const auto text = tr("The currently running application has requested yuzu to not exit.\n\n"
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h
index b62ff620c..77d992c54 100644
--- a/src/yuzu/uisettings.h
+++ b/src/yuzu/uisettings.h
@@ -93,10 +93,6 @@ struct Values {
93 Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui}; 93 Setting<bool> show_filter_bar{linkage, true, "showFilterBar", Category::Ui};
94 Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui}; 94 Setting<bool> show_status_bar{linkage, true, "showStatusBar", Category::Ui};
95 95
96 Setting<bool> confirm_before_closing{
97 linkage, true, "confirmClose", Category::UiGeneral, Settings::Specialization::Default,
98 true, true};
99
100 SwitchableSetting<ConfirmStop> confirm_before_stopping{linkage, 96 SwitchableSetting<ConfirmStop> confirm_before_stopping{linkage,
101 ConfirmStop::Ask_Always, 97 ConfirmStop::Ask_Always,
102 "confirmStop", 98 "confirmStop",