Compare commits

..

1 Commits

Author SHA1 Message Date
xbzk b60cbf8023 [debug] debug knobs adjustments 2026-08-28 23:21:45 -03:00
154 changed files with 1546 additions and 1560 deletions
-20
View File
@@ -69,26 +69,6 @@ if (YUZU_STATIC_ROOM)
set(fmt_FORCE_BUNDLED ON)
endif()
# my unity/jumbo build
option(ENABLE_UNITY_BUILD "Enable Unity/Jumbo build" OFF)
# 0 compiles all files in
# not ideal, but if you're going gung-ho with a unity build, expect failure
# MSVC physically can't compile that many files into one TU, so we limit it to 100.
if (MSVC)
set(_unity_default 100)
else()
set(_unity_default 0)
endif()
set(UNITY_BATCH_SIZE ${_unity_default} CACHE STRING "Unity build batch size")
if(MSVC AND ENABLE_UNITY_BUILD)
message(STATUS "Unity build")
# Unity builds need big objects for MSVC...
add_compile_options(/bigobj)
endif()
# qt stuff
option(ENABLE_QT "Enable the Qt frontend" ON)
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
-1
View File
@@ -39,7 +39,6 @@ These options control dependencies.
- This option is subject for removal.
- `YUZU_TESTS` (ON) Compile tests - requires Catch2
- `ENABLE_LTO` (OFF) Enable link-time optimization
- `ENABLE_UNITY_BUILD` (OFF) Enables "Unity/Jumbo" builds
- Not recommended on Windows
- UNIX may be better off appending `-flto=thin` to compiler args
- `USE_FASTER_LINKER` (OFF) Check if a faster linker is available
+27 -11
View File
@@ -43,6 +43,7 @@ This guide will walk you through adding a new boolean toggle setting to Eden's c
Firstly add your desired toggle:
Example: `src/common/setting.h`
```cpp
SwitchableSetting<bool> your_setting_name{linkage, false, "your_setting_name", Category::RendererExtensions};
```
@@ -67,6 +68,7 @@ Common Categories:
Add the toggle to the Qt UI, where you wish for it to appear and place it there.
Example: `src/qt_common/config/shared_translation.cpp`
```cpp
INSERT(Settings,
your_setting_name,
@@ -91,6 +93,7 @@ INSERT(Settings,
Add where it should be in the settings.
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/BooleanSetting.kt`
```kts
RENDERER_YOUR_SETTING_NAME("your_setting_name"),
```
@@ -106,6 +109,7 @@ RENDERER_YOUR_SETTING_NAME("your_setting_name"),
Add the toggle to the Kotlin (Android) UI
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/model/view/SettingsItem.kt`
```kts
put(
SwitchSetting(
@@ -123,6 +127,7 @@ put(
Add your setting within the right category.
Example: `src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsFragmentPresenter.kt`
```kts
add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
```
@@ -137,6 +142,7 @@ add(BooleanSetting.RENDERER_YOUR_SETTING_NAME.key)
Add your setting and description in the appropriate place.
Example: `src/android/app/src/main/res/values/strings.xml`
```xml
<string name="your_setting_name">Your Setting Display Name</string>
<string name="your_setting_name_description">Detailed description of what this setting does. Explain any caveats, requirements, or warnings here.</string>
@@ -150,6 +156,7 @@ Now the UI part is done find a place in the code for the toggle,
And use it to your heart's desire!
Example:
```cpp
const bool your_value = Settings::values.your_setting_name.GetValue();
@@ -196,25 +203,31 @@ Common advantages recap:
#### Accessing Debug Knobs (dev side)
Use the `Settings::getDebugKnobAt(u8 i)` function to check if a specific bit is set:
Use the `Settings::GetDebugKnobAt(u8 i)` function to check if a specific bit is set:
```cpp
//cpp side
#include "common/settings.h"
//To use it as a general purpose uint var:
unsigned int debug_knobs = Settings::values.debug_knobs.GetValue();
// Check if bit 0 is set
bool feature_enabled = Settings::getDebugKnobAt(0);
bool feature_enabled = Settings::GetDebugKnobAt(0);
// Check if bit 15 is set
bool another_feature = Settings::getDebugKnobAt(15);
bool another_feature = Settings::GetDebugKnobAt(15);
```
```kts
//kotlin side
import org.yuzu.yuzu_emu.features.settings.model.Settings
//To use it as a general purpose uint var
val debug_knobs: Int = UShortSetting.DEBUG_KNOBS.getInt()
// Check if bit x is set
bool feature_enabled = Settings.getDebugKnobAt(x); //x as integer from 0 to 15
bool feature_enabled = Settings.GetDebugKnobAt(x); //x as integer from 0 to 15
```
The function returns `true` if the specified bit (0-15) is set in the `debug_knobs` value, `false` otherwise.
@@ -247,6 +260,7 @@ There are two main confusions when talking about knobs:
Sometimes when an user reports: knobs 1 and 2 gets better performance, dev may get confuse whether he means the knobs 1 and 2 literally, or the 1st and 2nd knobs (knobs 0 and 1).
Debug knobs are **zero-based**, which means:
* The first knob is the knob(0) (or knob0 henceforth), and the last one is the 15 (knob15, likewise)
* You can talk: "knob0 is enabled/disabled", "In this video i was using only knobs 0 and 2", etc.
@@ -259,6 +273,7 @@ Whenever you're instructing tests or reporting results, be precise about whether
ALWAYS use the word in PLURAL (knobs), without mentioning which one, to refer to the setting, aka multiple knobs at once:
Examples:
- **knobs=0**: no knobs enabled
- **knobs=1**: knob0 enabled, others disabled
- **knobs=2**: knob1 enabled, others disabled
@@ -270,6 +285,7 @@ Examples:
Use the word in SINGULAR (knob), or in plural but referring which ones, when meaning multiple knobs at once:
Examples:
- **knob0**: knob 0 enabled, others disabled
- **knob1**: knob 1 enabled, others disabled
- **knobs 0 and 1**: knobs 0 and 1 enabled, others disabled
@@ -282,12 +298,12 @@ Examples:
```cpp
void SomeFunction() {
if (Settings::getDebugKnobAt(0)) {
if (Settings::GetDebugKnobAt(0)) {
LOG_DEBUG(Common, "Debug feature 0 is enabled");
// Additional debug code here
}
if (Settings::getDebugKnobAt(1)) {
if (Settings::GetDebugKnobAt(1)) {
LOG_DEBUG(Common, "Debug feature 1 is enabled");
// Different debug behavior
}
@@ -299,7 +315,7 @@ void SomeFunction() {
```cpp
bool UseOptimizedPath() {
// Skip optimization if debug bit 2 is set for testing
return !Settings::getDebugKnobAt(2);
return !Settings::GetDebugKnobAt(2);
}
```
@@ -308,13 +324,13 @@ bool UseOptimizedPath() {
```cpp
void ExperimentalFeature() {
static constexpr u8 EXPERIMENTAL_FEATURE_BIT = 3;
if (!Settings::getDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
if (!Settings::GetDebugKnobAt(EXPERIMENTAL_FEATURE_BIT)) {
// Fallback to stable implementation
StableImplementation();
return;
}
// Experimental implementation
ExperimentalImplementation();
}
-5
View File
@@ -7,11 +7,6 @@
# Enable modules to include each other's files
include_directories(.)
if (ENABLE_UNITY_BUILD)
set(CMAKE_UNITY_BUILD ON)
set(CMAKE_UNITY_BUILD_BATCH_SIZE ${UNITY_BATCH_SIZE})
endif()
# Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
add_subdirectory(dynarmic)
@@ -220,7 +220,7 @@ object NativeLibrary {
external fun refreshThreadPolicies()
external fun getDebugKnobAt(index: Int): Boolean
external fun GetDebugKnobAt(index: Int): Boolean
/**
* Set the current speed limit to the configured turbo speed.
@@ -35,8 +35,8 @@ object Settings {
fun getPlayerString(player: Int): String =
YuzuApplication.appContext.getString(R.string.preferences_player, player)
fun getDebugKnobAt(index: Int): Boolean {
return org.yuzu.yuzu_emu.NativeLibrary.getDebugKnobAt(index)
fun GetDebugKnobAt(index: Int): Boolean {
return org.yuzu.yuzu_emu.NativeLibrary.GetDebugKnobAt(index)
}
const val PREF_FIRST_APP_LAUNCH = "FirstApplicationLaunch"
@@ -11,8 +11,7 @@ import org.yuzu.yuzu_emu.utils.NativeConfig
enum class ShortSetting(override val key: String) : AbstractShortSetting {
RENDERER_SPEED_LIMIT("speed_limit"),
RENDERER_TURBO_SPEED_LIMIT("turbo_speed_limit"),
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit"),
DEBUG_KNOBS("debug_knobs")
RENDERER_SLOW_SPEED_LIMIT("slow_speed_limit")
;
override fun getShort(needsGlobal: Boolean): Short = NativeConfig.getShort(key, needsGlobal)
@@ -29,4 +28,4 @@ enum class ShortSetting(override val key: String) : AbstractShortSetting {
override fun getValueAsString(needsGlobal: Boolean): String = getShort(needsGlobal).toString()
override fun reset() = NativeConfig.setShort(key, defaultValue)
}
}
@@ -0,0 +1,30 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
package org.yuzu.yuzu_emu.features.settings.model
import org.yuzu.yuzu_emu.utils.NativeConfig
enum class UShortSetting(override val key: String) : AbstractIntSetting {
DEBUG_KNOBS("debug_knobs")
;
override fun getInt(needsGlobal: Boolean): Int =
NativeConfig.getUnsignedShort(key, needsGlobal)
override fun setInt(value: Int) {
if (NativeConfig.isPerGameConfigLoaded()) {
global = false
}
NativeConfig.setUnsignedShort(key, value)
}
override val defaultValue: Int by lazy { NativeConfig.getDefaultToString(key).toInt() }
override fun getValueAsString(needsGlobal: Boolean): String = getInt(needsGlobal).toString()
override fun reset() = NativeConfig.setUnsignedShort(key, defaultValue)
}
@@ -20,6 +20,7 @@ import org.yuzu.yuzu_emu.features.settings.model.IntSetting
import org.yuzu.yuzu_emu.features.settings.model.LongSetting
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
import org.yuzu.yuzu_emu.network.NetDataValidators
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
import org.yuzu.yuzu_emu.utils.NativeConfig
@@ -1034,7 +1035,7 @@ abstract class SettingsItem(
)
put(
SpinBoxSetting(
ShortSetting.DEBUG_KNOBS,
UShortSetting.DEBUG_KNOBS,
titleId = R.string.debug_knobs,
descriptionId = R.string.debug_knobs_description,
valueHint = R.string.debug_knobs_hint,
@@ -25,6 +25,7 @@ import org.yuzu.yuzu_emu.features.settings.model.Settings
import org.yuzu.yuzu_emu.features.settings.model.Settings.MenuTag
import org.yuzu.yuzu_emu.features.settings.model.ShortSetting
import org.yuzu.yuzu_emu.features.settings.model.StringSetting
import org.yuzu.yuzu_emu.features.settings.model.UShortSetting
import org.yuzu.yuzu_emu.features.settings.model.view.*
import org.yuzu.yuzu_emu.utils.InputHandler
import org.yuzu.yuzu_emu.utils.LosslessScalingHelper
@@ -1326,7 +1327,7 @@ class SettingsFragmentPresenter(
add(HeaderSetting(R.string.general))
add(ShortSetting.DEBUG_KNOBS.key)
add(UShortSetting.DEBUG_KNOBS.key)
add(StringSetting.PROGRAM_ARGS.key)
if (!NativeConfig.isPerGameConfigLoaded()) {
@@ -80,6 +80,12 @@ object NativeConfig {
@Synchronized
external fun setShort(key: String, value: Short)
@Synchronized
external fun getUnsignedShort(key: String, needsGlobal: Boolean): Int
@Synchronized
external fun setUnsignedShort(key: String, value: Int)
@Synchronized
external fun getInt(key: String, needsGlobal: Boolean): Int
+2 -2
View File
@@ -1300,8 +1300,8 @@ void Java_org_yuzu_yuzu_1emu_NativeLibrary_refreshThreadPolicies(JNIEnv* env, jo
Common::RefreshThreadPolicies();
}
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_getDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
return static_cast<jboolean>(Settings::getDebugKnobAt(static_cast<u8>(index)));
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_GetDebugKnobAt(JNIEnv* env, jobject jobj, jint index) {
return static_cast<jboolean>(Settings::GetDebugKnobAt(static_cast<u8>(index)));
}
void Java_org_yuzu_yuzu_1emu_NativeLibrary_setTurboSpeedLimit(JNIEnv *env, jobject jobj, jboolean enabled) {
@@ -130,6 +130,25 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setShort(JNIEnv* env, jobject ob
setting->SetValue(value);
}
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getUnsignedShort(JNIEnv* env, jobject obj,
jstring jkey,
jboolean needGlobal) {
auto setting = getSetting<u16>(env, jkey);
if (setting == nullptr) {
return -1;
}
return static_cast<jint>(setting->GetValue(static_cast<bool>(needGlobal)));
}
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setUnsignedShort(JNIEnv* env, jobject obj,
jstring jkey, jint value) {
auto setting = getSetting<u16>(env, jkey);
if (setting == nullptr) {
return;
}
setting->SetValue(static_cast<u16>(value));
}
jint Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getInt(JNIEnv* env, jobject obj, jstring jkey,
jboolean needGlobal) {
auto setting = getSetting<int>(env, jkey);
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,11 +5,17 @@
#include "common/assert.h"
namespace AudioCore::ADSP::OpusDecoder {
namespace {
bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
} // namespace
u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) {
if (channel_count == 1 || channel_count == 2)
if (!IsValidChannelCount(channel_count)) {
return 0;
return u32(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count);
}
return static_cast<u32>(sizeof(OpusDecodeObject)) + opus_decoder_get_size(channel_count);
}
OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) {
@@ -22,6 +22,10 @@ namespace AudioCore::ADSP::OpusDecoder {
namespace {
constexpr size_t OpusStreamCountMax = 255;
bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
bool IsValidMultiStreamChannelCount(u32 channel_count) {
return channel_count <= OpusStreamCountMax;
}
-3
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
+4 -4
View File
@@ -14,16 +14,14 @@
#include "core/core_timing.h"
#include "core/hle/kernel/k_event.h"
namespace AudioCore::AudioIn {
// See texture_cache/util.h
template<typename T, size_t N>
#if BOOST_VERSION >= 108100 || __GNUC__ > 12
[[nodiscard]] static inline boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
[[nodiscard]] boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
return v;
}
#else
[[nodiscard]] static inline std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
[[nodiscard]] std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
std::vector<T> u;
for (auto const& e : v)
u.push_back(e);
@@ -31,6 +29,8 @@ template<typename T, size_t N>
}
#endif
namespace AudioCore::AudioIn {
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
: system{system_}, buffer_event{event_},
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
+4 -3
View File
@@ -14,15 +14,14 @@
#include "core/core_timing.h"
#include "core/hle/kernel/k_event.h"
namespace AudioCore::AudioOut {
// See texture_cache/util.h
template<typename T, size_t N>
#if BOOST_VERSION >= 108100 || __GNUC__ > 12
[[nodiscard]] static inline boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
[[nodiscard]] boost::container::static_vector<T, N> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
return v;
}
#else
[[nodiscard]] static inline std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
[[nodiscard]] std::vector<T> FixStaticVectorADL(const boost::container::static_vector<T, N>& v) {
std::vector<T> u;
for (auto const& e : v)
u.push_back(e);
@@ -30,6 +29,8 @@ template<typename T, size_t N>
}
#endif
namespace AudioCore::AudioOut {
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
: system{system_}, buffer_event{event_},
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -16,7 +16,7 @@ namespace AudioCore::Renderer {
* @param memory - Core memory for writing.
* @param aux_info - Memory address pointing to the AuxInfo to reset.
*/
static void CaptureResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_info) {
static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_info) {
if (aux_info == 0) {
LOG_ERROR(Service_Audio, "Aux info is 0!");
return;
@@ -134,7 +134,7 @@ void CaptureCommand::Process(const AudioRenderer::CommandListProcessor& processo
WriteAuxBufferDsp(*processor.memory, send_buffer_info, send_buffer, count_max, input_buffer,
processor.sample_count, write_offset, update_count);
} else {
CaptureResetAuxBufferDsp(*processor.memory, send_buffer_info);
ResetAuxBufferDsp(*processor.memory, send_buffer_info);
}
}
+8 -9
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2011 Google, Inc.
// SPDX-FileContributor: Geoff Pike
// SPDX-FileContributor: Jyrki Alakuijala
@@ -30,6 +27,8 @@
#define WORDS_BIGENDIAN 1
#endif
using namespace std;
namespace Common {
static u64 unaligned_load64(const char* p) {
@@ -136,18 +135,18 @@ static u64 HashLen17to32(const char* s, size_t len) {
// Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b.
static std::pair<u64, u64> WeakHashLen32WithSeeds(u64 w, u64 x, u64 y, u64 z, u64 a, u64 b) {
static pair<u64, u64> WeakHashLen32WithSeeds(u64 w, u64 x, u64 y, u64 z, u64 a, u64 b) {
a += w;
b = Rotate(b + a + z, 21);
u64 c = a;
a += x;
a += y;
b += Rotate(a, 44);
return std::make_pair(a + z, b + c);
return make_pair(a + z, b + c);
}
// Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty.
static std::pair<u64, u64> WeakHashLen32WithSeeds(const char* s, u64 a, u64 b) {
static pair<u64, u64> WeakHashLen32WithSeeds(const char* s, u64 a, u64 b) {
return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
b);
}
@@ -190,8 +189,8 @@ u64 CityHash64(const char* s, size_t len) {
u64 x = Fetch64(s + len - 40);
u64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
u64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
std::pair<u64, u64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
std::pair<u64, u64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
pair<u64, u64> v = WeakHashLen32WithSeeds(s + len - 64, len, z);
pair<u64, u64> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
x = x * k1 + Fetch64(s);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks.
@@ -259,7 +258,7 @@ u128 CityHash128WithSeed(const char* s, size_t len, u128 seed) {
// We expect len >= 128 to be the common case. Keep 56 bytes of state:
// v, w, x, y, and z.
std::pair<u64, u64> v, w;
pair<u64, u64> v, w;
u64 x = seed[0];
u64 y = seed[1];
u64 z = len * k1;
-2
View File
@@ -16,5 +16,3 @@
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#undef INVALID_SOCKET
+1 -1
View File
@@ -146,7 +146,7 @@ void LogSettings() {
#undef LOG_PATH
}
bool getDebugKnobAt(u8 i) {
bool GetDebugKnobAt(u8 i) {
return (values.debug_knobs.GetValue() & (1 << (i & 0xF))) != 0;
}
+2 -2
View File
@@ -904,7 +904,7 @@ struct Values {
0,
65535,
"debug_knobs",
Category::Debugging,
Category::System,
Specialization::Countable,
true,
true};
@@ -947,7 +947,7 @@ constexpr u32 MAX_FRAME_GEN_MULTIPLIER = 4;
[[nodiscard]] size_t FrameGenMaxGenerations();
bool getDebugKnobAt(u8 i);
bool GetDebugKnobAt(u8 i);
void UpdateGPUAccuracy();
bool IsGPULevelHigh();
+8 -7
View File
@@ -7,18 +7,19 @@
#pragma once
#include <dynarmic/interface/halt_reason.h>
#include "core/arm/arm_interface.h"
namespace Core {
inline constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step;
inline constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort;
inline constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2;
inline constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3;
inline constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4;
inline constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6;
constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step;
constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort;
constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2;
constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3;
constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4;
constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6;
[[nodiscard]] inline constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) {
static_assert(u64(HaltReason::StepThread) == u64(StepThread));
static_assert(u64(HaltReason::DataAbort) == u64(DataAbort));
static_assert(u64(HaltReason::BreakLoop) == u64(BreakLoop));
-1
View File
@@ -38,7 +38,6 @@ constexpr u32 CpuClockTargetMhz(Settings::CpuClock clock) {
}
}
#undef CreateEvent
std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
return std::make_shared<EventType>(std::move(callback), std::move(name));
}
+5 -5
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -185,13 +185,13 @@ static_assert(sizeof(SaveDataFilter) == 0x48, "SaveDataFilter has invalid size."
static_assert(std::is_trivially_copyable_v<SaveDataFilter>,
"Data type must be trivially copyable.");
struct SaveDataHashSalt {
struct HashSalt {
static constexpr size_t Size = 32;
std::array<u8, Size> value;
};
static_assert(std::is_trivially_copyable_v<SaveDataHashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(SaveDataHashSalt) == SaveDataHashSalt::Size);
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(HashSalt) == HashSalt::Size);
struct SaveDataCreationInfo2 {
@@ -210,7 +210,7 @@ struct SaveDataCreationInfo2 {
u8 reserved1;
bool is_hash_salt_enabled;
u8 reserved2;
SaveDataHashSalt hash_salt;
HashSalt hash_salt;
SaveDataMetaType meta_type;
u8 reserved3;
s32 meta_size;
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -14,7 +11,7 @@
#include "core/file_sys/vfs/vfs.h"
#include "core/file_sys/vfs/vfs_vector.h"
namespace FileSys::RomFSBuilder {
namespace FileSys {
constexpr u64 FS_MAX_PATH = 0x301;
+1 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,7 +9,7 @@
#include "common/common_types.h"
#include "core/file_sys/vfs/vfs.h"
namespace FileSys::RomFSBuilder {
namespace FileSys {
struct RomFSBuildDirectoryContext;
struct RomFSBuildFileContext;
+10 -10
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -38,7 +38,7 @@ struct RomFSHeader {
};
static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
struct RomFSDirectoryEntry {
struct DirectoryEntry {
u32_le parent;
u32_le sibling;
u32_le child_dir;
@@ -46,9 +46,9 @@ struct RomFSDirectoryEntry {
u32_le hash;
u32_le name_length;
};
static_assert(sizeof(RomFSDirectoryEntry) == 0x18, "RomFSDirectoryEntry has incorrect size.");
static_assert(sizeof(DirectoryEntry) == 0x18, "DirectoryEntry has incorrect size.");
struct RomFSFileEntry {
struct FileEntry {
u32_le parent;
u32_le sibling;
u64_le offset;
@@ -56,7 +56,7 @@ struct RomFSFileEntry {
u32_le hash;
u32_le name_length;
};
static_assert(sizeof(RomFSFileEntry) == 0x20, "RomFSFileEntry has incorrect size.");
static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
struct RomFSTraversalContext {
RomFSHeader header;
@@ -84,14 +84,14 @@ std::pair<EntryType, std::string> GetEntry(const RomFSTraversalContext& ctx, siz
return {entry, std::move(name)};
}
std::pair<RomFSDirectoryEntry, std::string> GetDirectoryEntry(const RomFSTraversalContext& ctx,
std::pair<DirectoryEntry, std::string> GetDirectoryEntry(const RomFSTraversalContext& ctx,
size_t directory_offset) {
return GetEntry<RomFSDirectoryEntry, &RomFSTraversalContext::directory_meta>(ctx, directory_offset);
return GetEntry<DirectoryEntry, &RomFSTraversalContext::directory_meta>(ctx, directory_offset);
}
std::pair<RomFSFileEntry, std::string> GetFileEntry(const RomFSTraversalContext& ctx,
std::pair<FileEntry, std::string> GetFileEntry(const RomFSTraversalContext& ctx,
size_t file_offset) {
return GetEntry<RomFSFileEntry, &RomFSTraversalContext::file_meta>(ctx, file_offset);
return GetEntry<FileEntry, &RomFSTraversalContext::file_meta>(ctx, file_offset);
}
void ProcessFile(const RomFSTraversalContext& ctx, u32 this_file_offset,
@@ -163,7 +163,7 @@ VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
if (dir == nullptr)
return nullptr;
RomFSBuilder::RomFSBuildContext ctx{dir, ext};
RomFSBuildContext ctx{dir, ext};
return ConcatenatedVfsFile::MakeConcatenatedFile(0, dir->GetName(), ctx.Build());
}
+1 -7
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -10,12 +10,6 @@
#include "common/fs/path_util.h"
#include "core/file_sys/vfs/vfs.h"
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
#undef CopyFile
#undef MoveFile
namespace FileSys {
VfsFilesystem::VfsFilesystem(VirtualDir root_) : root(std::move(root_)) {}
+1 -5
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -99,10 +99,6 @@ private:
std::string name;
};
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
// An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
// Vector data is supplied upon construction.
class VectorVfsDirectory : public VfsDirectory {
+1 -5
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-late
@@ -13,10 +13,6 @@
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
#undef OutputDebugString
#undef GetObject
#undef CreateProcess
namespace Kernel::Svc {
static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) {
+10 -10
View File
@@ -11,11 +11,7 @@
namespace Kernel::Svc {
namespace {
[[nodiscard]] inline constexpr bool IsValidSetAddressRange(u64 address, u64 size) {
return address + size > address;
}
[[nodiscard]] inline constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
switch (perm) {
case MemoryPermission::None:
case MemoryPermission::Read:
@@ -26,6 +22,13 @@ namespace {
}
}
// Checks if address + size is greater than the given address
// This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero.
constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address;
}
// Helper function that performs the common sanity checks for svcMapMemory
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing
// in the same order.
@@ -50,17 +53,14 @@ Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr
R_THROW(ResultInvalidSize);
}
// Checks if address + size is greater than the given address
// This can return false if the size causes an overflow of a 64-bit type
// or if the given size is zero.
if (!IsValidSetAddressRange(dst_addr, size)) {
if (!IsValidAddressRange(dst_addr, size)) {
LOG_ERROR(Kernel_SVC,
"Destination is not a valid address range, addr={:#016x}, size={:#016x}",
dst_addr, size);
R_THROW(ResultInvalidCurrentMemory);
}
if (!IsValidSetAddressRange(src_addr, size)) {
if (!IsValidAddressRange(src_addr, size)) {
LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr={:#016x}, size={:#016x}",
src_addr, size);
R_THROW(ResultInvalidCurrentMemory);
@@ -11,11 +11,11 @@
namespace Kernel::Svc {
namespace {
[[nodiscard]] inline constexpr bool IsValidAddressRange(u64 address, u64 size) {
constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address;
}
[[nodiscard]] inline constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
switch (perm) {
case Svc::MemoryPermission::None:
case Svc::MemoryPermission::Read:
+6 -5
View File
@@ -9,12 +9,13 @@
#include "core/hle/service/ipc_helpers.h"
namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioIn::IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager, size_t session_id,
const std::string& device_name, const AudioCore::AudioIn::AudioInParameter& in_params,
IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioInParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"},
event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<AudioCore::AudioIn::In>(system_,
event{service_context.CreateEvent("AudioInEvent")}, impl{std::make_shared<In>(system_,
manager, event,
session_id)} {
// clang-format off
@@ -70,12 +71,12 @@ Result IAudioIn::Stop() {
R_RETURN(impl->StopSystem());
}
Result IAudioIn::AppendAudioInBuffer(InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
Result IAudioIn::AppendAudioInBuffer(InArray<AudioInBuffer, BufferAttr_HipcMapAlias> buffer,
u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioInBufferAuto(buffer, buffer_client_ptr));
}
Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioCore::AudioIn::AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
Result IAudioIn::AppendAudioInBufferAuto(InArray<AudioInBuffer, BufferAttr_HipcAutoSelect> buffer,
u64 buffer_client_ptr) {
if (buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,6 +7,7 @@
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioInManager::IAudioInManager(Core::System& system_)
: ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
@@ -36,11 +34,11 @@ Result IAudioInManager::ListAudioIns(
R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count));
}
Result IAudioInManager::OpenAudioIn(Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal,
Result IAudioInManager::OpenAudioIn(Out<AudioInParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioIn::AudioInParameter parameter,
AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
@@ -55,9 +53,9 @@ Result IAudioInManager::ListAudioInsAuto(
}
Result IAudioInManager::OpenAudioInAuto(
Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioCore::AudioIn::AudioInParameter parameter,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
@@ -72,10 +70,10 @@ Result IAudioInManager::ListAudioInsAutoFiltered(
}
Result IAudioInManager::OpenAudioInProtocolSpecified(
Out<AudioCore::AudioIn::AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
Out<AudioInParameterInternal> out_parameter_internal, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol,
AudioCore::AudioIn::AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
AudioInParameter parameter, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called");
@@ -106,7 +104,7 @@ Result IAudioInManager::OpenAudioInProtocolSpecified(
auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal =
AudioCore::AudioIn::AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())};
+5 -4
View File
@@ -13,9 +13,10 @@
#include "core/hle/service/service.h"
namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOut::IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, size_t session_id,
const std::string& device_name, const AudioCore::AudioOut::AudioOutParameter& in_params,
IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioOutParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
@@ -67,12 +68,12 @@ Result IAudioOut::Stop() {
}
Result IAudioOut::AppendAudioOutBuffer(
InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) {
InArray<AudioOutBuffer, BufferAttr_HipcMapAlias> audio_out_buffer, u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr));
}
Result IAudioOut::AppendAudioOutBufferAuto(
InArray<AudioCore::AudioOut::AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) {
InArray<AudioOutBuffer, BufferAttr_HipcAutoSelect> audio_out_buffer, u64 buffer_client_ptr) {
if (audio_out_buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
R_THROW(Audio::ResultInsufficientBuffer);
@@ -11,6 +11,7 @@
#include "core/memory.h"
namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOutManager::IAudioOutManager(Core::System& system_)
: ServiceFramework{system_, "audout:u"}
@@ -35,11 +36,11 @@ Result IAudioOutManager::ListAudioOuts(
R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count));
}
Result IAudioOutManager::OpenAudioOut(Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
Result IAudioOutManager::OpenAudioOut(Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioOut::AudioOutParameter parameter,
AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) {
R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
@@ -61,10 +62,10 @@ Result IAudioOutManager::ListAudioOutsAuto(
}
Result IAudioOutManager::OpenAudioOutAuto(
Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal,
Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioCore::AudioOut::AudioOutParameter parameter,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
if (!process_handle) {
LOG_ERROR(Service_Audio, "Failed to get process handle");
@@ -94,7 +95,7 @@ Result IAudioOutManager::OpenAudioOutAuto(
auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal =
AudioCore::AudioOut::AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())};
@@ -4,20 +4,21 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/renderer/audio_renderer.h"
#include "core/hle/service/audio/audio_renderer.h"
#include "core/hle/service/cmif_serialization.h"
namespace Service::Audio {
using namespace AudioCore::Renderer;
IAudioRenderer::IAudioRenderer(Core::System& system_, AudioCore::Renderer::Manager& manager_,
IAudioRenderer::IAudioRenderer(Core::System& system_, Manager& manager_,
AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_},
impl{std::make_unique<AudioCore::Renderer::Renderer>(system_, manager, rendered_event)}, process_handle{process_handle_} {
impl{std::make_unique<Renderer>(system_, manager, rendered_event)}, process_handle{
process_handle_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
@@ -14,13 +14,16 @@
#include <cstring>
namespace Service::News {
namespace {
[[nodiscard]] inline std::string_view ToStringViewNDS(std::span<const char> buf) {
std::string_view ToStringView(std::span<const char> buf) {
const std::string_view sv{buf.data(), buf.size()};
const auto nul = sv.find('\0');
return nul == std::string_view::npos ? sv : sv.substr(0, nul);
}
} // namespace
INewsDataService::INewsDataService(Core::System& system_)
: ServiceFramework{system_, "INewsDataService"} {
static const FunctionInfo functions[] = {
@@ -52,7 +55,7 @@ bool INewsDataService::TryOpen(std::string_view key, std::string_view user) {
const auto list = NewsStorage::Instance().ListAll();
if (!list.empty()) {
if (auto found = NewsStorage::Instance().FindByNewsId(ToStringViewNDS(list.front().news_id))) {
if (auto found = NewsStorage::Instance().FindByNewsId(ToStringView(list.front().news_id))) {
opened_payload = std::move(found->payload);
return true;
}
@@ -64,7 +67,7 @@ bool INewsDataService::TryOpen(std::string_view key, std::string_view user) {
Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) {
EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS({reinterpret_cast<const char*>(name.data()), name.size()});
const auto key = ToStringView({reinterpret_cast<const char*>(name.data()), name.size()});
if (TryOpen(key, {})) {
R_SUCCEED();
@@ -76,8 +79,8 @@ Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) {
Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) {
EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS(record.news_id);
const auto user = ToStringViewNDS(record.user_id);
const auto key = ToStringView(record.news_id);
const auto user = ToStringView(record.user_id);
if (TryOpen(key, user)) {
R_SUCCEED();
@@ -89,8 +92,8 @@ Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) {
Result INewsDataService::OpenWithNewsRecord(NewsRecord record) {
EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS(record.news_id);
const auto user = ToStringViewNDS(record.user_id);
const auto key = ToStringView(record.news_id);
const auto user = ToStringView(record.user_id);
if (TryOpen(key, user)) {
R_SUCCEED();
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -15,13 +15,13 @@
namespace Service::News {
namespace {
[[nodiscard]] inline std::string_view ToStringView(std::span<const u8> buf) {
std::string_view ToStringView(std::span<const u8> buf) {
if (buf.empty()) return {};
auto data = reinterpret_cast<const char*>(buf.data());
return {data, strnlen(data, buf.size())};
}
[[nodiscard]] inline std::string_view ToStringView(std::span<const char> buf) {
std::string_view ToStringView(std::span<const char> buf) {
if (buf.empty()) return {};
return {buf.data(), strnlen(buf.data(), buf.size())};
}
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -9,8 +6,6 @@
namespace Service::News {
#undef CreateEvent
IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_)
: ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_,
"IOverwriteEventHolder"} {
@@ -18,8 +18,6 @@
#include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h"
#undef GetCurrentTime
namespace Service::Capture {
AlbumManager::AlbumManager(Core::System& system_) : system{system_} {}
-2
View File
@@ -19,8 +19,6 @@
#include "core/hle/service/server_manager.h"
#include "core/reporter.h"
#undef far
namespace Service::Fatal {
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
@@ -32,10 +32,6 @@
#include "core/hle/service/server_manager.h"
#include "core/loader/loader.h"
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
namespace Service::FileSystem {
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
-2
View File
@@ -27,8 +27,6 @@
#include "core/hle/service/ipc_helpers.h"
#include "core/memory.h"
#undef SendMessage
namespace Service {
SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_)
+1 -2
View File
@@ -212,9 +212,8 @@ struct NifmNetworkProfileData {
NifmWirelessSettingData wireless_setting_data{};
IpSettingData ip_setting_data{};
};
static_assert(sizeof(NifmNetworkProfileData) == 0x18E,
"NifmNetworkProfileData has incorrect size.");
#pragma pack(pop)
static_assert(sizeof(NifmNetworkProfileData) == 0x18E, "NifmNetworkProfileData has incorrect size.");
struct PendingProfile {
std::array<char, 0x21> ssid{};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,8 +10,6 @@
namespace Service::PSC::Time {
class ContextWriter;
#undef GetCurrentTime
class SystemClockCore {
public:
explicit SystemClockCore(SteadyClockCore& steady_clock) : m_steady_clock{steady_clock} {}
@@ -19,8 +19,6 @@ class System;
namespace Service::PSC::Time {
#undef GetCurrentTime
class SystemClock final : public ServiceFramework<SystemClock> {
public:
explicit SystemClock(Core::System& system, SystemClockCore& system_clock_core, bool can_write_clock, bool can_write_uninitialized_clock);
+90 -90
View File
@@ -54,11 +54,11 @@ void PutValue(std::span<u8> buffer, const T& t) {
} // Anonymous namespace
void NetworkBSD::PollWork::Execute(NetworkBSD* bsd) {
void BSD::PollWork::Execute(BSD* bsd) {
std::tie(ret, bsd_errno) = bsd->PollImpl(write_buffer, read_buffer, nfds, timeout);
}
void NetworkBSD::PollWork::Response(HLERequestContext& ctx) {
void BSD::PollWork::Response(HLERequestContext& ctx) {
if (write_buffer.size() > 0) {
ctx.WriteBuffer(write_buffer);
}
@@ -69,11 +69,11 @@ void NetworkBSD::PollWork::Response(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno);
}
void NetworkBSD::AcceptWork::Execute(NetworkBSD* bsd) {
void BSD::AcceptWork::Execute(BSD* bsd) {
std::tie(ret, bsd_errno) = bsd->AcceptImpl(fd, write_buffer);
}
void NetworkBSD::AcceptWork::Response(HLERequestContext& ctx) {
void BSD::AcceptWork::Response(HLERequestContext& ctx) {
if (write_buffer.size() > 0) {
ctx.WriteBuffer(write_buffer);
}
@@ -85,22 +85,22 @@ void NetworkBSD::AcceptWork::Response(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(write_buffer.size()));
}
void NetworkBSD::ConnectWork::Execute(NetworkBSD* bsd) {
void BSD::ConnectWork::Execute(BSD* bsd) {
bsd_errno = bsd->ConnectImpl(fd, addr);
}
void NetworkBSD::ConnectWork::Response(HLERequestContext& ctx) {
void BSD::ConnectWork::Response(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1);
rb.PushEnum(bsd_errno);
}
void NetworkBSD::RecvWork::Execute(NetworkBSD* bsd) {
void BSD::RecvWork::Execute(BSD* bsd) {
std::tie(ret, bsd_errno) = bsd->RecvImpl(fd, flags, message);
}
void NetworkBSD::RecvWork::Response(HLERequestContext& ctx) {
void BSD::RecvWork::Response(HLERequestContext& ctx) {
ctx.WriteBuffer(message);
IPC::ResponseBuilder rb{ctx, 4};
@@ -109,11 +109,11 @@ void NetworkBSD::RecvWork::Response(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno);
}
void NetworkBSD::RecvFromWork::Execute(NetworkBSD* bsd) {
void BSD::RecvFromWork::Execute(BSD* bsd) {
std::tie(ret, bsd_errno) = bsd->RecvFromImpl(fd, flags, message, addr);
}
void NetworkBSD::RecvFromWork::Response(HLERequestContext& ctx) {
void BSD::RecvFromWork::Response(HLERequestContext& ctx) {
ctx.WriteBuffer(message, 0);
if (!addr.empty()) {
ctx.WriteBuffer(addr, 1);
@@ -126,29 +126,29 @@ void NetworkBSD::RecvFromWork::Response(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(addr.size()));
}
void NetworkBSD::SendWork::Execute(NetworkBSD* bsd) {
void BSD::SendWork::Execute(BSD* bsd) {
std::tie(ret, bsd_errno) = bsd->SendImpl(fd, flags, message);
}
void NetworkBSD::SendWork::Response(HLERequestContext& ctx) {
void BSD::SendWork::Response(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<s32>(ret);
rb.PushEnum(bsd_errno);
}
void NetworkBSD::SendToWork::Execute(NetworkBSD* bsd) {
void BSD::SendToWork::Execute(BSD* bsd) {
std::tie(ret, bsd_errno) = bsd->SendToImpl(fd, flags, message, addr);
}
void NetworkBSD::SendToWork::Response(HLERequestContext& ctx) {
void BSD::SendToWork::Response(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
rb.Push<s32>(ret);
rb.PushEnum(bsd_errno);
}
void NetworkBSD::RegisterClient(HLERequestContext& ctx) {
void BSD::RegisterClient(HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3};
@@ -157,7 +157,7 @@ void NetworkBSD::RegisterClient(HLERequestContext& ctx) {
rb.Push<s32>(0); // bsd errno
}
void NetworkBSD::StartMonitoring(HLERequestContext& ctx) {
void BSD::StartMonitoring(HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2};
@@ -165,7 +165,7 @@ void NetworkBSD::StartMonitoring(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
}
void NetworkBSD::Socket(HLERequestContext& ctx) {
void BSD::Socket(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u32 domain = rp.Pop<u32>();
const u32 type = rp.Pop<u32>();
@@ -200,7 +200,7 @@ void BSD::SocketExempt(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno);
}
void NetworkBSD::Select(HLERequestContext& ctx) {
void BSD::Select(HLERequestContext& ctx) {
LOG_DEBUG(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4};
@@ -210,7 +210,7 @@ void NetworkBSD::Select(HLERequestContext& ctx) {
rb.Push<u32>(0); // bsd errno
}
void NetworkBSD::Poll(HLERequestContext& ctx) {
void BSD::Poll(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 nfds = rp.Pop<s32>();
const s32 timeout = rp.Pop<s32>();
@@ -225,7 +225,7 @@ void NetworkBSD::Poll(HLERequestContext& ctx) {
});
}
void NetworkBSD::Accept(HLERequestContext& ctx) {
void BSD::Accept(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -237,7 +237,7 @@ void NetworkBSD::Accept(HLERequestContext& ctx) {
});
}
void NetworkBSD::Bind(HLERequestContext& ctx) {
void BSD::Bind(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -245,7 +245,7 @@ void NetworkBSD::Bind(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer()));
}
void NetworkBSD::Connect(HLERequestContext& ctx) {
void BSD::Connect(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -257,7 +257,7 @@ void NetworkBSD::Connect(HLERequestContext& ctx) {
});
}
void NetworkBSD::GetPeerName(HLERequestContext& ctx) {
void BSD::GetPeerName(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -275,7 +275,7 @@ void NetworkBSD::GetPeerName(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(write_buffer.size()));
}
void NetworkBSD::GetSockName(HLERequestContext& ctx) {
void BSD::GetSockName(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -293,7 +293,7 @@ void NetworkBSD::GetSockName(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(write_buffer.size()));
}
void NetworkBSD::GetSockOpt(HLERequestContext& ctx) {
void BSD::GetSockOpt(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
const u32 level = rp.Pop<u32>();
@@ -315,7 +315,7 @@ void NetworkBSD::GetSockOpt(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(optval.size()));
}
void NetworkBSD::Listen(HLERequestContext& ctx) {
void BSD::Listen(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
const s32 backlog = rp.Pop<s32>();
@@ -325,7 +325,7 @@ void NetworkBSD::Listen(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, ListenImpl(fd, backlog));
}
void NetworkBSD::Fcntl(HLERequestContext& ctx) {
void BSD::Fcntl(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
const s32 cmd = rp.Pop<s32>();
@@ -341,7 +341,7 @@ void NetworkBSD::Fcntl(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno);
}
void NetworkBSD::SetSockOpt(HLERequestContext& ctx) {
void BSD::SetSockOpt(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -355,7 +355,7 @@ void NetworkBSD::SetSockOpt(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
}
void NetworkBSD::Shutdown(HLERequestContext& ctx) {
void BSD::Shutdown(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -366,7 +366,7 @@ void NetworkBSD::Shutdown(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, ShutdownImpl(fd, how));
}
void NetworkBSD::Recv(HLERequestContext& ctx) {
void BSD::Recv(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -381,7 +381,7 @@ void NetworkBSD::Recv(HLERequestContext& ctx) {
});
}
void NetworkBSD::RecvFrom(HLERequestContext& ctx) {
void BSD::RecvFrom(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -398,7 +398,7 @@ void NetworkBSD::RecvFrom(HLERequestContext& ctx) {
});
}
void NetworkBSD::Send(HLERequestContext& ctx) {
void BSD::Send(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -413,7 +413,7 @@ void NetworkBSD::Send(HLERequestContext& ctx) {
});
}
void NetworkBSD::SendTo(HLERequestContext& ctx) {
void BSD::SendTo(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
const u32 flags = rp.Pop<u32>();
@@ -429,7 +429,7 @@ void NetworkBSD::SendTo(HLERequestContext& ctx) {
});
}
void NetworkBSD::Write(HLERequestContext& ctx) {
void BSD::Write(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -442,7 +442,7 @@ void NetworkBSD::Write(HLERequestContext& ctx) {
});
}
void NetworkBSD::Read(HLERequestContext& ctx) {
void BSD::Read(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -454,7 +454,7 @@ void NetworkBSD::Read(HLERequestContext& ctx) {
rb.Push<u32>(0); // bsd errno
}
void NetworkBSD::Close(HLERequestContext& ctx) {
void BSD::Close(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>();
@@ -464,7 +464,7 @@ void NetworkBSD::Close(HLERequestContext& ctx) {
}
/// @brief Only bsd:s is able to dup()
void NetworkBSD::DuplicateSocket(HLERequestContext& ctx) {
void BSD::DuplicateSocket(HLERequestContext& ctx) {
struct InputParameters {
s32 fd;
u64 reserved;
@@ -505,7 +505,7 @@ void NetworkBSD::DuplicateSocket(HLERequestContext& ctx) {
}
}
void NetworkBSD::EventFd(HLERequestContext& ctx) {
void BSD::EventFd(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const u64 initval = rp.Pop<u64>();
const u32 flags = rp.Pop<u32>();
@@ -516,12 +516,12 @@ void NetworkBSD::EventFd(HLERequestContext& ctx) {
}
template <typename Work>
void NetworkBSD::ExecuteWork(HLERequestContext& ctx, Work work) {
void BSD::ExecuteWork(HLERequestContext& ctx, Work work) {
work.Execute(this);
work.Response(ctx);
}
std::pair<s32, Errno> NetworkBSD::SocketImpl(Domain domain, Type type, Protocol protocol) {
std::pair<s32, Errno> BSD::SocketImpl(Domain domain, Type type, Protocol protocol) {
// user bsd:u has restrictions on SOCK_SEQPACKET and SOCK_RAW
if (is_user && (type == Type::SEQPACKET || type == Type::RAW)) {
if (type == Type::RAW && domain == Domain::INET && protocol == Protocol::ICMP) {
@@ -565,7 +565,7 @@ std::pair<s32, Errno> NetworkBSD::SocketImpl(Domain domain, Type type, Protocol
return {fd, Errno::SUCCESS};
}
std::pair<s32, Errno> NetworkBSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
std::pair<s32, Errno> BSD::PollImpl(std::vector<u8>& write_buffer, std::span<const u8> read_buffer,
s32 nfds, s32 timeout) {
if (nfds <= 0) {
// When no entries are provided, -1 is returned with errno zero
@@ -632,7 +632,7 @@ std::pair<s32, Errno> NetworkBSD::PollImpl(std::vector<u8>& write_buffer, std::s
return Translate(result);
}
std::pair<s32, Errno> NetworkBSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
std::pair<s32, Errno> BSD::AcceptImpl(s32 fd, std::vector<u8>& write_buffer) {
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
}
@@ -660,7 +660,7 @@ std::pair<s32, Errno> NetworkBSD::AcceptImpl(s32 fd, std::vector<u8>& write_buff
return {new_fd, Errno::SUCCESS};
}
Errno NetworkBSD::BindImpl(s32 fd, std::span<const u8> addr) {
Errno BSD::BindImpl(s32 fd, std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -675,7 +675,7 @@ Errno NetworkBSD::BindImpl(s32 fd, std::span<const u8> addr) {
return Translate(file_descriptors[fd]->socket->Bind(Translate(addr_in)));
}
Errno NetworkBSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
Errno BSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -698,7 +698,7 @@ Errno NetworkBSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
return result;
}
Errno NetworkBSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
Errno BSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -720,7 +720,7 @@ Errno NetworkBSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
return Translate(bsd_errno);
}
Errno NetworkBSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
Errno BSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -742,7 +742,7 @@ Errno NetworkBSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
return Translate(bsd_errno);
}
Errno NetworkBSD::ListenImpl(s32 fd, s32 backlog) {
Errno BSD::ListenImpl(s32 fd, s32 backlog) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -753,7 +753,7 @@ Errno NetworkBSD::ListenImpl(s32 fd, s32 backlog) {
return Translate(file_descriptors[fd]->socket->Listen(backlog));
}
std::pair<s32, Errno> NetworkBSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) {
std::pair<s32, Errno> BSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) {
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
}
@@ -783,7 +783,7 @@ std::pair<s32, Errno> NetworkBSD::FcntlImpl(s32 fd, FcntlCmd cmd, s32 arg) {
}
}
Errno NetworkBSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval) {
Errno BSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector<u8>& optval) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -818,7 +818,7 @@ Errno NetworkBSD::GetSockOptImpl(s32 fd, u32 level, OptName optname, std::vector
}
}
Errno NetworkBSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) {
Errno BSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<const u8> optval) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -872,7 +872,7 @@ Errno NetworkBSD::SetSockOptImpl(s32 fd, u32 level, OptName optname, std::span<c
}
}
Errno NetworkBSD::ShutdownImpl(s32 fd, s32 how) {
Errno BSD::ShutdownImpl(s32 fd, s32 how) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -884,7 +884,7 @@ Errno NetworkBSD::ShutdownImpl(s32 fd, s32 how) {
return Translate(file_descriptors[fd]->socket->Shutdown(host_how));
}
std::pair<s32, Errno> NetworkBSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message) {
std::pair<s32, Errno> BSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& message) {
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
}
@@ -911,7 +911,7 @@ std::pair<s32, Errno> NetworkBSD::RecvImpl(s32 fd, u32 flags, std::vector<u8>& m
return {ret, bsd_errno};
}
std::pair<s32, Errno> NetworkBSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
std::pair<s32, Errno> BSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8>& message,
std::vector<u8>& addr) {
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
@@ -958,7 +958,7 @@ std::pair<s32, Errno> NetworkBSD::RecvFromImpl(s32 fd, u32 flags, std::vector<u8
return {ret, bsd_errno};
}
std::pair<s32, Errno> NetworkBSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) {
std::pair<s32, Errno> BSD::SendImpl(s32 fd, u32 flags, std::span<const u8> message) {
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
}
@@ -969,7 +969,7 @@ std::pair<s32, Errno> NetworkBSD::SendImpl(s32 fd, u32 flags, std::span<const u8
return Translate(file_descriptors[fd]->socket->Send(message, flags));
}
std::pair<s32, Errno> NetworkBSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
std::pair<s32, Errno> BSD::SendToImpl(s32 fd, u32 flags, std::span<const u8> message,
std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF};
@@ -991,7 +991,7 @@ std::pair<s32, Errno> NetworkBSD::SendToImpl(s32 fd, u32 flags, std::span<const
return Translate(file_descriptors[fd]->socket->SendTo(flags, message, p_addr_in));
}
Errno NetworkBSD::CloseImpl(s32 fd) {
Errno BSD::CloseImpl(s32 fd) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -1011,7 +1011,7 @@ Errno NetworkBSD::CloseImpl(s32 fd) {
return bsd_errno;
}
std::variant<s32, Errno> NetworkBSD::DuplicateSocketImpl(s32 fd) {
std::variant<s32, Errno> BSD::DuplicateSocketImpl(s32 fd) {
if (!IsFileDescriptorValid(fd)) {
return Errno::BADF;
}
@@ -1030,7 +1030,7 @@ std::variant<s32, Errno> NetworkBSD::DuplicateSocketImpl(s32 fd) {
return new_fd;
}
std::optional<std::shared_ptr<Network::SocketBase>> NetworkBSD::GetSocket(s32 fd) {
std::optional<std::shared_ptr<Network::SocketBase>> BSD::GetSocket(s32 fd) {
if (!IsFileDescriptorValid(fd)) {
return std::nullopt;
}
@@ -1041,7 +1041,7 @@ std::optional<std::shared_ptr<Network::SocketBase>> NetworkBSD::GetSocket(s32 fd
return file_descriptors[fd]->socket;
}
s32 NetworkBSD::FindFreeFileDescriptorHandle() noexcept {
s32 BSD::FindFreeFileDescriptorHandle() noexcept {
for (s32 fd = 0; fd < static_cast<s32>(file_descriptors.size()); ++fd) {
if (!file_descriptors[fd]) {
return fd;
@@ -1050,7 +1050,7 @@ s32 NetworkBSD::FindFreeFileDescriptorHandle() noexcept {
return -1;
}
bool NetworkBSD::IsFileDescriptorValid(s32 fd) const noexcept {
bool BSD::IsFileDescriptorValid(s32 fd) const noexcept {
if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
LOG_ERROR(Service, "Invalid file descriptor handle={}", fd);
return false;
@@ -1062,7 +1062,7 @@ bool NetworkBSD::IsFileDescriptorValid(s32 fd) const noexcept {
return true;
}
void NetworkBSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept {
void BSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) const noexcept {
IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess);
@@ -1070,7 +1070,7 @@ void NetworkBSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) con
rb.PushEnum(bsd_errno);
}
void NetworkBSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
for (auto& optional_descriptor : file_descriptors) {
if (!optional_descriptor.has_value()) {
continue;
@@ -1080,43 +1080,43 @@ void NetworkBSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
}
}
NetworkBSD::NetworkBSD(Core::System& system_, const char* name, bool is_user_)
BSD::BSD(Core::System& system_, const char* name, bool is_user_)
: ServiceFramework{system_, name}
, is_user{is_user_} {
// clang-format off
static const FunctionInfo functions[] = {
{0, &NetworkBSD::RegisterClient, "RegisterClient"},
{1, &NetworkBSD::StartMonitoring, "StartMonitoring"},
{2, &NetworkBSD::Socket, "Socket"},
{3, &NetworkBSD::SocketExempt, "SocketExempt"},
{0, &BSD::RegisterClient, "RegisterClient"},
{1, &BSD::StartMonitoring, "StartMonitoring"},
{2, &BSD::Socket, "Socket"},
{3, &BSD::SocketExempt, "SocketExempt"},
{4, nullptr, "Open"},
{5, &NetworkBSD::Select, "Select"},
{6, &NetworkBSD::Poll, "Poll"},
{5, &BSD::Select, "Select"},
{6, &BSD::Poll, "Poll"},
{7, nullptr, "Sysctl"},
{8, &NetworkBSD::Recv, "Recv"},
{9, &NetworkBSD::RecvFrom, "RecvFrom"},
{10, &NetworkBSD::Send, "Send"},
{11, &NetworkBSD::SendTo, "SendTo"},
{12, &NetworkBSD::Accept, "Accept"},
{13, &NetworkBSD::Bind, "Bind"},
{14, &NetworkBSD::Connect, "Connect"},
{15, &NetworkBSD::GetPeerName, "GetPeerName"},
{16, &NetworkBSD::GetSockName, "GetSockName"},
{17, &NetworkBSD::GetSockOpt, "GetSockOpt"},
{18, &NetworkBSD::Listen, "Listen"},
{8, &BSD::Recv, "Recv"},
{9, &BSD::RecvFrom, "RecvFrom"},
{10, &BSD::Send, "Send"},
{11, &BSD::SendTo, "SendTo"},
{12, &BSD::Accept, "Accept"},
{13, &BSD::Bind, "Bind"},
{14, &BSD::Connect, "Connect"},
{15, &BSD::GetPeerName, "GetPeerName"},
{16, &BSD::GetSockName, "GetSockName"},
{17, &BSD::GetSockOpt, "GetSockOpt"},
{18, &BSD::Listen, "Listen"},
{19, nullptr, "Ioctl"},
{20, &NetworkBSD::Fcntl, "Fcntl"},
{21, &NetworkBSD::SetSockOpt, "SetSockOpt"},
{22, &NetworkBSD::Shutdown, "Shutdown"},
{20, &BSD::Fcntl, "Fcntl"},
{21, &BSD::SetSockOpt, "SetSockOpt"},
{22, &BSD::Shutdown, "Shutdown"},
{23, nullptr, "ShutdownAllSockets"},
{24, &NetworkBSD::Write, "Write"},
{25, &NetworkBSD::Read, "Read"},
{26, &NetworkBSD::Close, "Close"},
{27, &NetworkBSD::DuplicateSocket, "DuplicateSocket"},
{24, &BSD::Write, "Write"},
{25, &BSD::Read, "Read"},
{26, &BSD::Close, "Close"},
{27, &BSD::DuplicateSocket, "DuplicateSocket"},
{28, nullptr, "GetResourceStatistics"},
{29, nullptr, "RecvMMsg"}, //3.0.0+
{30, nullptr, "SendMMsg"}, //3.0.0+
{31, &NetworkBSD::EventFd, "EventFd"}, //7.0.0+
{31, &BSD::EventFd, "EventFd"}, //7.0.0+
{32, nullptr, "RegisterResourceStatisticsName"}, //7.0.0+
{33, nullptr, "RegisterClientShared"}, //10.0.0+
{34, nullptr, "GetSocketStatistics"}, //15.0.0+
@@ -1144,13 +1144,13 @@ NetworkBSD::NetworkBSD(Core::System& system_, const char* name, bool is_user_)
}
}
NetworkBSD::~NetworkBSD() {
BSD::~BSD() {
if (auto room_member = Network::GetRoomMember().lock()) {
room_member->Unbind(proxy_packet_received);
}
}
std::unique_lock<std::mutex> NetworkBSD::LockService() noexcept {
std::unique_lock<std::mutex> BSD::LockService() noexcept {
return {};
}
+10 -10
View File
@@ -27,10 +27,10 @@ class Socket;
namespace Service::Sockets {
class NetworkBSD final : public ServiceFramework<NetworkBSD> {
class BSD final : public ServiceFramework<BSD> {
public:
explicit NetworkBSD(Core::System& system_, const char* name, bool is_user);
~NetworkBSD() override;
explicit BSD(Core::System& system_, const char* name, bool is_user);
~BSD() override;
// These methods are called from SSL; the first two are also called from
// this class for the corresponding IPC methods.
@@ -50,7 +50,7 @@ private:
};
struct PollWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 nfds;
@@ -62,7 +62,7 @@ private:
};
struct AcceptWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 fd;
@@ -72,7 +72,7 @@ private:
};
struct ConnectWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 fd;
@@ -81,7 +81,7 @@ private:
};
struct RecvWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 fd;
@@ -92,7 +92,7 @@ private:
};
struct RecvFromWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 fd;
@@ -104,7 +104,7 @@ private:
};
struct SendWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 fd;
@@ -115,7 +115,7 @@ private:
};
struct SendToWork {
void Execute(NetworkBSD* bsd);
void Execute(BSD* bsd);
void Response(HLERequestContext& ctx);
s32 fd;
+3 -3
View File
@@ -66,9 +66,9 @@ void LoopProcess(Core::System& system) {
server_manager->RegisterNamedService("ethc:c", std::make_shared<ETHC_C>(system));
server_manager->RegisterNamedService("ethc:i", std::make_shared<ETHC_I>(system));
server_manager->RegisterNamedService("bsd:s", std::make_shared<NetworkBSD>(system, "bsd:s", false));
server_manager->RegisterNamedService("bsd:u", std::make_shared<NetworkBSD>(system, "bsd:u", true));
server_manager->RegisterNamedService("bsd:a", std::make_shared<NetworkBSD>(system, "bsd:a", true));
server_manager->RegisterNamedService("bsd:s", std::make_shared<BSD>(system, "bsd:s", false));
server_manager->RegisterNamedService("bsd:u", std::make_shared<BSD>(system, "bsd:u", true));
server_manager->RegisterNamedService("bsd:a", std::make_shared<BSD>(system, "bsd:a", true));
server_manager->RegisterNamedService("bsd:nu", std::make_shared<BSD_NU>(system));
server_manager->RegisterNamedService("bsdcfg", std::make_shared<BSDCFG>(system, "bsdcfg"));
server_manager->RegisterNamedService("ifcfg", std::make_shared<BSDCFG>(system, "ifcfg"));
+2 -2
View File
@@ -129,7 +129,7 @@ public:
LOG_ERROR(Service_SSL,
"do_not_close_socket was changed after setting socket; is this right?");
} else {
auto bsd = system.ServiceManager().GetService<Service::Sockets::NetworkBSD>("bsd:u");
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
if (bsd) {
auto err = bsd->CloseImpl(fd);
if (err != Service::Sockets::Errno::SUCCESS) {
@@ -157,7 +157,7 @@ private:
Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) {
LOG_DEBUG(Service_SSL, "called, fd={}", fd);
ASSERT(!did_handshake);
auto bsd = system.ServiceManager().GetService<Service::Sockets::NetworkBSD>("bsd:u");
auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
auto const res_v = bsd->DuplicateSocketImpl(fd);
+6 -4
View File
@@ -17,9 +17,11 @@
namespace Loader {
[[nodiscard]] inline constexpr u32 PageAlignSizeKIP(u32 size) {
return u32((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
namespace {
constexpr u32 PageAlignSize(u32 size) {
return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
}
} // Anonymous namespace
AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_)
: AppLoader(std::move(file_)), kip(std::make_unique<FileSys::KIP>(file)) {}
@@ -74,11 +76,11 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
kip->GetKernelCapabilities());
Kernel::CodeSet codeset;
codeset.memory.resize(PageAlignSizeKIP(kip->GetBSSOffset()) + kip->GetBSSSize());
codeset.memory.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
const auto load_segment = [&codeset](Kernel::CodeSet::Segment& segment, std::span<const u8> data, u32 offset) {
segment.addr = offset;
segment.offset = offset;
segment.size = PageAlignSizeKIP(u32(data.size()));
segment.size = PageAlignSize(u32(data.size()));
std::memcpy(codeset.memory.data() + offset, data.data(), data.size());
};
load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset());
+7 -7
View File
@@ -148,8 +148,8 @@ bool AppLoader_NRO::IsHomebrew() {
nro_header.magic_ext2 == Common::MakeMagic('B', 'R', 'E', 'W');
}
[[nodiscard]] inline constexpr u32 PageAlignSizeNRO(u32 size) {
return u32((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
static constexpr u32 PageAlignSize(u32 size) {
return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
}
static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
@@ -166,9 +166,9 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
}
// Build program image
std::vector<u8> program_image(PageAlignSizeNRO(nro_header.file_size));
std::vector<u8> program_image(PageAlignSize(nro_header.file_size));
std::memcpy(program_image.data(), data.data(), program_image.size());
if (program_image.size() != PageAlignSizeNRO(nro_header.file_size)) {
if (program_image.size() != PageAlignSize(nro_header.file_size)) {
return {};
}
@@ -176,11 +176,11 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
for (std::size_t i = 0; i < nro_header.segments.size(); ++i) {
codeset.segments[i].addr = nro_header.segments[i].offset;
codeset.segments[i].offset = nro_header.segments[i].offset;
codeset.segments[i].size = PageAlignSizeNRO(nro_header.segments[i].size);
codeset.segments[i].size = PageAlignSize(nro_header.segments[i].size);
}
// Default .bss to NRO header bss size if MOD0 section doesn't exist
u32 bss_size{PageAlignSizeNRO(nro_header.bss_size)};
u32 bss_size{PageAlignSize(nro_header.bss_size)};
// Read MOD header
ModHeader mod_header{};
@@ -190,7 +190,7 @@ static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process,
const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')};
if (has_mod_header) {
// Resize program image to include .bss section and page align each section
bss_size = PageAlignSizeNRO(mod_header.bss_end_offset - mod_header.bss_start_offset);
bss_size = PageAlignSize(mod_header.bss_end_offset - mod_header.bss_start_offset);
}
codeset.DataSegment().size += bss_size;
+4 -4
View File
@@ -41,8 +41,8 @@ struct MODHeader {
};
static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size.");
[[nodiscard]] inline constexpr u32 PageAlignSizeNSO(u32 size) {
return u32((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
constexpr u32 PageAlignSize(u32 size) {
return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
}
} // Anonymous namespace
@@ -128,11 +128,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
}
codeset.DataSegment().size += nso_header.segments[2].bss_size;
u32 image_size = PageAlignSizeNSO(u32(codeset.memory.size()) + nso_header.segments[2].bss_size);
u32 image_size = PageAlignSize(u32(codeset.memory.size()) + nso_header.segments[2].bss_size);
codeset.memory.resize(image_size);
for (std::size_t i = 0; i < nso_header.segments.size(); ++i) {
codeset.segments[i].size = PageAlignSizeNSO(codeset.segments[i].size);
codeset.segments[i].size = PageAlignSize(codeset.segments[i].size);
}
// Apply patches if necessary
-2
View File
@@ -21,8 +21,6 @@
#include "hid_core/resource_manager.h"
#include "hid_core/resources/npad/npad.h"
#undef CreateEvent
namespace Core::Memory {
namespace {
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
-2
View File
@@ -28,8 +28,6 @@
#include "core/memory.h"
#include "core/reporter.h"
#undef far
namespace {
std::filesystem::path GetPath(std::string_view type, u64 title_id, std::string_view timestamp) {
-2
View File
@@ -52,8 +52,6 @@ void MemoryWriteWidth(Core::Memory::Memory& memory, u32 width, VAddr addr, u64 v
} // Anonymous namespace
#undef CreateEvent
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
: core_timing{core_timing_}, memory{memory_} {
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
@@ -31,7 +31,7 @@ using namespace oaknut::util;
namespace {
[[nodiscard]] inline bool IsOrdered(IR::AccType acctype) {
bool IsOrdered(IR::AccType acctype) {
return acctype == IR::AccType::ORDERED || acctype == IR::AccType::ORDEREDRW || acctype == IR::AccType::LIMITEDORDERED;
}
+2 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,6 +6,7 @@
#include "hid_core/hidbus/starlink.h"
namespace Service::HID {
constexpr u8 DEVICE_ID = 0x28;
Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_)
: HidbusBase(system_, service_context_) {}
@@ -37,7 +35,7 @@ void Starlink::OnUpdate() {
}
u8 Starlink::GetDeviceId() const {
return 0x28;
return DEVICE_ID;
}
u64 Starlink::GetReply(std::span<u8> out_data) const {
+2 -4
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,6 +6,7 @@
#include "hid_core/hidbus/stubbed.h"
namespace Service::HID {
constexpr u8 DEVICE_ID = 0xFF;
HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_)
: HidbusBase(system_, service_context_) {}
@@ -37,7 +35,7 @@ void HidbusStubbed::OnUpdate() {
}
u8 HidbusStubbed::GetDeviceId() const {
return 0xFF;
return DEVICE_ID;
}
u64 HidbusStubbed::GetReply(std::span<u8> out_data) const {
+9 -12
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@@ -11,6 +8,9 @@
#include "hid_core/irsensor/moment_processor.h"
namespace Service::IRS {
static constexpr auto format = Core::IrSensor::ImageTransferProcessorFormat::Size40x30;
static constexpr std::size_t ImageWidth = 40;
static constexpr std::size_t ImageHeight = 30;
MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
std::size_t npad_index)
@@ -80,9 +80,9 @@ void MomentProcessor::OnControllerUpdate(Core::HID::ControllerTriggerType type)
}
u8 MomentProcessor::GetPixel(const std::vector<u8>& data, std::size_t x, std::size_t y) const {
constexpr std::size_t ImageWidth = 40;
if ((y * ImageWidth) + x >= data.size())
if ((y * ImageWidth) + x >= data.size()) {
return 0;
}
return data[(y * ImageWidth) + x];
}
@@ -92,12 +92,9 @@ MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector
std::size_t width,
std::size_t height) const {
// The actual implementation is always 320x240
constexpr std::size_t RealWidth = 320;
constexpr std::size_t RealHeight = 240;
constexpr std::size_t Threshold = 30;
constexpr std::size_t ImageWidth = 40;
constexpr std::size_t ImageHeight = 30;
static constexpr std::size_t RealWidth = 320;
static constexpr std::size_t RealHeight = 240;
static constexpr std::size_t Threshold = 30;
MomentStatistic statistic{};
std::size_t active_points{};
@@ -146,7 +143,7 @@ void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig conf
static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
npad_device->SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat::Size40x30);
npad_device->SetCameraFormat(format);
}
} // namespace Service::IRS
+3 -6
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,14 +7,14 @@
#include "input_common/drivers/camera.h"
namespace InputCommon {
constexpr PadIdentifier camera_identifier = {
constexpr PadIdentifier identifier = {
.guid = Common::UUID{},
.port = 0,
.pad = 0,
};
Camera::Camera(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(camera_identifier);
PreSetController(identifier);
}
void Camera::SetCameraData(std::size_t width, std::size_t height, std::span<const u32> data) {
@@ -36,7 +33,7 @@ void Camera::SetCameraData(std::size_t width, std::size_t height, std::span<cons
}
}
SetCamera(camera_identifier, status);
SetCamera(identifier, status);
}
std::size_t Camera::getImageWidth() const {
+16 -16
View File
@@ -26,7 +26,7 @@ constexpr int mouse_axis_x = 0;
constexpr int mouse_axis_y = 1;
constexpr int wheel_axis_x = 2;
constexpr int wheel_axis_y = 3;
constexpr PadIdentifier mouse_identifier = {
constexpr PadIdentifier identifier = {
.guid = Common::UUID{},
.port = 0,
.pad = 0,
@@ -51,16 +51,16 @@ constexpr PadIdentifier touch_identifier = {
};
Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(mouse_identifier);
PreSetController(identifier);
PreSetController(real_mouse_identifier);
PreSetController(touch_identifier);
PreSetController(motion_identifier);
// Initialize all mouse axis
PreSetAxis(mouse_identifier, mouse_axis_x);
PreSetAxis(mouse_identifier, mouse_axis_y);
PreSetAxis(mouse_identifier, wheel_axis_x);
PreSetAxis(mouse_identifier, wheel_axis_y);
PreSetAxis(identifier, mouse_axis_x);
PreSetAxis(identifier, mouse_axis_y);
PreSetAxis(identifier, wheel_axis_x);
PreSetAxis(identifier, wheel_axis_y);
PreSetAxis(real_mouse_identifier, mouse_axis_x);
PreSetAxis(real_mouse_identifier, mouse_axis_y);
PreSetAxis(touch_identifier, mouse_axis_x);
@@ -88,8 +88,8 @@ void Mouse::UpdateStickInput() {
last_mouse_change *= maximum_stick_range;
}
SetAxis(mouse_identifier, mouse_axis_x, last_mouse_change.x);
SetAxis(mouse_identifier, mouse_axis_y, -last_mouse_change.y);
SetAxis(identifier, mouse_axis_x, last_mouse_change.x);
SetAxis(identifier, mouse_axis_y, -last_mouse_change.y);
// Decay input over time
const float clamped_length = (std::min)(1.0f, length);
@@ -165,8 +165,8 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
const float y_sensitivity =
Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity;
SetAxis(mouse_identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * x_sensitivity);
SetAxis(mouse_identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * y_sensitivity);
SetAxis(identifier, mouse_axis_x, static_cast<float>(mouse_move.x) * x_sensitivity);
SetAxis(identifier, mouse_axis_y, static_cast<float>(-mouse_move.y) * y_sensitivity);
last_motion_change = {
static_cast<float>(-mouse_move.y) * x_sensitivity,
@@ -192,7 +192,7 @@ void Mouse::TouchMove(f32 touch_x, f32 touch_y) {
}
void Mouse::PressButton(int x, int y, MouseButton button) {
SetButton(mouse_identifier, static_cast<int>(button), true);
SetButton(identifier, static_cast<int>(button), true);
// Set initial analog parameters
mouse_origin = {x, y};
@@ -211,13 +211,13 @@ void Mouse::PressTouchButton(f32 touch_x, f32 touch_y, MouseButton button) {
}
void Mouse::ReleaseButton(MouseButton button) {
SetButton(mouse_identifier, static_cast<int>(button), false);
SetButton(identifier, static_cast<int>(button), false);
SetButton(real_mouse_identifier, static_cast<int>(button), false);
SetButton(touch_identifier, static_cast<int>(button), false);
if (!IsMousePanningEnabled()) {
SetAxis(mouse_identifier, mouse_axis_x, 0);
SetAxis(mouse_identifier, mouse_axis_y, 0);
SetAxis(identifier, mouse_axis_x, 0);
SetAxis(identifier, mouse_axis_y, 0);
}
last_motion_change.x = 0;
@@ -230,8 +230,8 @@ void Mouse::MouseWheelChange(int x, int y) {
wheel_position.x += x;
wheel_position.y += y;
last_motion_change.z += static_cast<f32>(y);
SetAxis(mouse_identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
SetAxis(mouse_identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
SetAxis(identifier, wheel_axis_x, static_cast<f32>(wheel_position.x));
SetAxis(identifier, wheel_axis_y, static_cast<f32>(wheel_position.y));
}
void Mouse::ReleaseAllButtons() {
+8 -11
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,14 +6,14 @@
namespace InputCommon {
constexpr PadIdentifier touch_screen_identifier = {
constexpr PadIdentifier identifier = {
.guid = Common::UUID{},
.port = 0,
.pad = 0,
};
TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(touch_screen_identifier);
PreSetController(identifier);
ReleaseAllTouch();
}
@@ -29,9 +26,9 @@ void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) {
}
const auto i = index.value();
fingers[i].is_active = true;
SetButton(touch_screen_identifier, static_cast<int>(i), true);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2), x);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2 + 1), y);
SetButton(identifier, static_cast<int>(i), true);
SetAxis(identifier, static_cast<int>(i * 2), x);
SetAxis(identifier, static_cast<int>(i * 2 + 1), y);
}
void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) {
@@ -58,9 +55,9 @@ void TouchScreen::TouchReleased(std::size_t finger_id) {
}
const auto i = index.value();
fingers[i].is_enabled = false;
SetButton(touch_screen_identifier, static_cast<int>(i), false);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2), 0.0f);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2 + 1), 0.0f);
SetButton(identifier, static_cast<int>(i), false);
SetAxis(identifier, static_cast<int>(i * 2), 0.0f);
SetAxis(identifier, static_cast<int>(i * 2 + 1), 0.0f);
}
std::optional<std::size_t> TouchScreen::GetIndexFromFingerId(std::size_t finger_id) const {
+7 -7
View File
@@ -600,7 +600,7 @@ void TestCommunication(const std::string& host, u16 port, const std::function<vo
}
CalibrationConfigurationJob::CalibrationConfigurationJob(
const std::string& host, u16 port, std::function<void(CalibrationStatus)> status_callback,
const std::string& host, u16 port, std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback) {
std::thread([=, this] {
@@ -609,13 +609,13 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
u16 max_x{};
u16 max_y{};
auto current_status = CalibrationStatus::Initialized;
Status current_status{Status::Initialized};
SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, [&](Response::PadData data) {
constexpr u16 CALIBRATION_THRESHOLD = 100;
if (current_status == CalibrationStatus::Initialized) {
if (current_status == Status::Initialized) {
// Receiving data means the communication is ready now
current_status = CalibrationStatus::Ready;
current_status = Status::Ready;
status_callback(current_status);
}
if (data.touch[0].is_active == 0) {
@@ -624,9 +624,9 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x, data.touch[0].y);
min_x = (std::min)(min_x, u16(data.touch[0].x));
min_y = (std::min)(min_y, u16(data.touch[0].y));
if (current_status == CalibrationStatus::Ready) {
if (current_status == Status::Ready) {
// First touch - min data (min_x/min_y)
current_status = CalibrationStatus::Stage1Completed;
current_status = Status::Stage1Completed;
status_callback(current_status);
}
if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD &&
@@ -635,7 +635,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
// configuration
max_x = data.touch[0].x;
max_y = data.touch[0].y;
current_status = CalibrationStatus::Completed;
current_status = Status::Completed;
data_callback(min_x, min_y, max_x, max_y);
status_callback(current_status);
+2 -5
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2018 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -166,7 +163,7 @@ private:
/// An async job allowing configuration of the touchpad calibration.
class CalibrationConfigurationJob {
public:
enum class CalibrationStatus {
enum class Status {
Initialized,
Ready,
Stage1Completed,
@@ -179,7 +176,7 @@ public:
* @param data_callback Called when calibration data is ready
*/
explicit CalibrationConfigurationJob(const std::string& host, u16 port,
std::function<void(CalibrationStatus)> status_callback,
std::function<void(Status)> status_callback,
std::function<void(u16, u16, u16, u16)> data_callback);
~CalibrationConfigurationJob();
void Stop();
+4 -4
View File
@@ -15,7 +15,7 @@
#include "input_common/drivers/virtual_amiibo.h"
namespace InputCommon {
constexpr PadIdentifier virtual_amiibo_identifier = {
constexpr PadIdentifier identifier = {
.guid = Common::UUID{},
.port = 0,
.pad = 0,
@@ -228,13 +228,13 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) {
status.state = Common::Input::NfcState::NewAmiibo,
memcpy(nfc_data.data(), data.data(), data.size_bytes());
memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length);
SetNfc(virtual_amiibo_identifier, status);
SetNfc(identifier, status);
return Info::Success;
}
VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
if (state == State::TagNearby) {
SetNfc(virtual_amiibo_identifier, status);
SetNfc(identifier, status);
return Info::Success;
}
@@ -248,7 +248,7 @@ VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
state = State::WaitingForAmiibo;
status.state = Common::Input::NfcState::AmiiboRemoved;
SetNfc(virtual_amiibo_identifier, status);
SetNfc(identifier, status);
status.tag_type = 0;
return Info::Success;
}
+10 -9
View File
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,7 +5,6 @@
#include <array>
#include <vector>
#include <string>
#include "common/common_types.h"
namespace Network {
@@ -122,21 +118,26 @@ private:
template <typename T>
Packet& Packet::Read(std::vector<T>& out_data) {
// First extract the size
u32 size = 0;
Read(size);
out_data.resize(size);
for (auto& elem : out_data) {
Read(elem);
// Then extract the data
for (std::size_t i = 0; i < out_data.size(); ++i) {
T character;
Read(character);
out_data[i] = character;
}
return *this;
}
template <typename T, std::size_t S>
Packet& Packet::Read(std::array<T, S>& out_data) {
for (auto& elem : out_data) {
Read(elem);
for (std::size_t i = 0; i < out_data.size(); ++i) {
T character;
Read(character);
out_data[i] = character;
}
return *this;
}
+2 -2
View File
@@ -832,7 +832,7 @@ void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) {
in_packet.IgnoreBytes(sizeof(u8)); // Protocol
bool broadcast = false;
bool broadcast;
in_packet.Read(broadcast); // Broadcast
Packet out_packet;
@@ -886,7 +886,7 @@ void Room::RoomImpl::HandleLdnPacket(const ENetEvent* event) {
IPv4Address remote_ip;
in_packet.Read(remote_ip); // Remote IP
bool broadcast = false;
bool broadcast;
in_packet.Read(broadcast); // Broadcast
Packet out_packet;
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -48,6 +45,11 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU
}
}
bool IsInputArray(Stage stage) {
return stage == Stage::Geometry || stage == Stage::TessellationControl ||
stage == Stage::TessellationEval;
}
std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) {
return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
}
@@ -7,7 +7,6 @@
#pragma once
#include "common/common_types.h"
#include "shader_recompiler/stage.h"
#include "shader_recompiler/backend/glasm/reg_alloc.h"
namespace Shader::IR {
@@ -19,11 +18,6 @@ class Value;
namespace Shader::Backend::GLASM {
[[nodiscard]] inline bool IsInputArray(Stage stage) {
return stage == Stage::Geometry || stage == Stage::TessellationControl
|| stage == Stage::TessellationEval;
}
class EmitContext;
// Microinstruction emitters
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,92 +7,94 @@
namespace Shader::Backend::GLASM {
#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
void EmitGetRegister(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetRegister(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetPred(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetPred(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetGotoVariable(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetGotoVariable(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetIndirectBranchVariable(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetIndirectBranchVariable(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetZFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetSFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetCFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetOFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetZFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetSFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetCFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitSetOFlag(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetZeroFromOp(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetSignFromOp(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetCarryFromOp(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetOverflowFromOp(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetSparseFromOp(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
void EmitGetInBoundsFromOp(EmitContext& ctx) {
throw NotImplementedException("GLASM instruction {}", __LINE__);
NotImplemented();
}
} // namespace Shader::Backend::GLASM
@@ -1,12 +1,8 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "shader_recompiler/backend/bindings.h"
#include "shader_recompiler/backend/glasm/emit_glasm.h"
#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
#include "shader_recompiler/frontend/ir/program.h"
#include "shader_recompiler/profile.h"
@@ -25,6 +21,11 @@ std::string_view InterpDecorator(Interpolation interp) {
}
throw InvalidArgument("Invalid interpolation {}", interp);
}
bool IsInputArray(Stage stage) {
return stage == Stage::Geometry || stage == Stage::TessellationControl ||
stage == Stage::TessellationEval;
}
} // Anonymous namespace
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,13 +9,14 @@
namespace Shader::Backend::GLSL {
namespace {
constexpr std::string_view SWIZZLE{"xyzw"};
void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view composite,
std::string_view object, u32 index) {
if (result == composite) {
// The result is aliased with the composite
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
} else {
ctx.Add("{}={};{}.{}={};", result, composite, result, "xyzw"[index], object);
ctx.Add("{}={};{}.{}={};", result, composite, result, SWIZZLE[index], object);
}
}
} // Anonymous namespace
@@ -40,17 +38,17 @@ void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, std::string_v
void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
u32 index) {
ctx.AddU32("{}={}.{};", inst, composite, "xyzw"[index]);
ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
}
void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
u32 index) {
ctx.AddU32("{}={}.{};", inst, composite, "xyzw"[index]);
ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
}
void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
u32 index) {
ctx.AddU32("{}={}.{};", inst, composite, "xyzw"[index]);
ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
}
void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
@@ -148,17 +146,17 @@ void EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst& inst, std::string_v
void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
u32 index) {
ctx.AddF32("{}={}.{};", inst, composite, "xyzw"[index]);
ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
}
void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
u32 index) {
ctx.AddF32("{}={}.{};", inst, composite, "xyzw"[index]);
ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
}
void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
u32 index) {
ctx.AddF32("{}={}.{};", inst, composite, "xyzw"[index]);
ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
}
void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
@@ -205,16 +203,16 @@ void EmitCompositeExtractF64x4([[maybe_unused]] EmitContext& ctx) {
void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object,
u32 index) {
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
}
void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object,
u32 index) {
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
}
void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object,
u32 index) {
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
}
} // namespace Shader::Backend::GLSL
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -14,13 +11,14 @@
namespace Shader::Backend::GLSL {
namespace {
constexpr char SWIZZLE[]{"xyzw"};
u32 CbufIndex(u32 offset) {
return (offset / 4) % 4;
}
char OffsetSwizzle(u32 offset) {
return "xyzw"[CbufIndex(offset)];
return SWIZZLE[CbufIndex(offset)];
}
bool IsInputArray(Stage stage) {
@@ -32,6 +30,10 @@ std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) {
return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
}
std::string_view OutputVertexIndex(EmitContext& ctx) {
return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
}
std::string ChooseCbuf(EmitContext& ctx, const IR::Value& binding, std::string_view index) {
if (binding.IsImmediate()) {
return fmt::format("{}_cbuf{}[{}]", ctx.stage_name, binding.U32(), index);
@@ -277,7 +279,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
const u32 index{IR::GenericAttributeIndex(attr)};
const u32 attr_element{IR::GenericAttributeElement(attr)};
const GenericElementInfo& info{ctx.output_generics.at(index).at(attr_element)};
const auto output_decorator = ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
const auto output_decorator{OutputVertexIndex(ctx)};
if (info.num_components == 1) {
ctx.Add("{}{}={};", info.name, output_decorator, value);
} else {
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,13 +10,14 @@
namespace Shader::Backend::GLSL {
namespace {
constexpr char cas_loop[]{"for(;;){{uint old_value={};uint "
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
"if(cas_result==old_value){{break;}}}}"};
void SsboWriteCas(EmitContext& ctx, const IR::Value& binding, std::string_view offset_var,
std::string_view value, std::string_view bit_offset, u32 num_bits) {
const auto ssbo{fmt::format("{}_ssbo{}[{}>>2]", ctx.stage_name, binding.U32(), offset_var)};
ctx.Add(
"for(;;){{uint old_value={};uint "
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
"if(cas_result==old_value){{break;}}}}", ssbo, ssbo, ssbo, value, bit_offset, num_bits);
ctx.Add(cas_loop, ssbo, ssbo, ssbo, value, bit_offset, num_bits);
}
} // Anonymous namespace
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,13 +7,14 @@
namespace Shader::Backend::GLSL {
namespace {
constexpr char cas_loop[]{"for(;;){{uint old_value={};uint "
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
"if(cas_result==old_value){{break;}}}}"};
void SharedWriteCas(EmitContext& ctx, std::string_view offset, std::string_view value,
std::string_view bit_offset, u32 num_bits) {
const auto smem{fmt::format("smem[{}>>2]", offset)};
ctx.Add(
"for(;;){{uint old_value={};uint "
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
"if(cas_result==old_value){{break;}}}}", smem, smem, smem, value, bit_offset, num_bits);
ctx.Add(cas_loop, smem, smem, smem, value, bit_offset, num_bits);
}
} // Anonymous namespace
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,6 +9,9 @@
namespace Shader::Backend::GLSL {
namespace {
std::string_view OutputVertexIndex(EmitContext& ctx) {
return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
}
void InitializeOutputVaryings(EmitContext& ctx) {
if (ctx.uses_geometry_passthrough) {
@@ -25,7 +25,7 @@ void InitializeOutputVaryings(EmitContext& ctx) {
continue;
}
const auto& info_array{ctx.output_generics.at(index)};
const auto output_decorator = ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
const auto output_decorator{OutputVertexIndex(ctx)};
size_t element{};
while (element < info_array.size()) {
const auto& info{info_array.at(element)};
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,7 +9,7 @@
namespace Shader::Backend::SPIRV {
namespace {
Id DecorateNoContraction(EmitContext& ctx, IR::Inst* inst, Id op) {
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) {
const auto flags{inst->Flags<IR::FpControl>()};
if (flags.no_contraction) {
ctx.Decorate(op, spv::Decoration::NoContraction);
@@ -61,27 +61,27 @@ Id EmitFPAbs64(EmitContext& ctx, Id value) {
}
Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return DecorateNoContraction(ctx, inst, ctx.OpFAdd(ctx.F16[1], a, b));
return Decorate(ctx, inst, ctx.OpFAdd(ctx.F16[1], a, b));
}
Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return DecorateNoContraction(ctx, inst, ctx.OpFAdd(ctx.F32[1], a, b));
return Decorate(ctx, inst, ctx.OpFAdd(ctx.F32[1], a, b));
}
Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return DecorateNoContraction(ctx, inst, ctx.OpFAdd(ctx.F64[1], a, b));
return Decorate(ctx, inst, ctx.OpFAdd(ctx.F64[1], a, b));
}
Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
return DecorateNoContraction(ctx, inst, ctx.OpFma(ctx.F16[1], a, b, c));
return Decorate(ctx, inst, ctx.OpFma(ctx.F16[1], a, b, c));
}
Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
return DecorateNoContraction(ctx, inst, ctx.OpFma(ctx.F32[1], a, b, c));
return Decorate(ctx, inst, ctx.OpFma(ctx.F32[1], a, b, c));
}
Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
return DecorateNoContraction(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c));
return Decorate(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c));
}
Id EmitFPMax32(EmitContext& ctx, Id a, Id b) {
@@ -101,15 +101,15 @@ Id EmitFPMin64(EmitContext& ctx, Id a, Id b) {
}
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return DecorateNoContraction(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b));
return Decorate(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b));
}
Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return DecorateNoContraction(ctx, inst, ctx.OpFMul(ctx.F32[1], a, b));
return Decorate(ctx, inst, ctx.OpFMul(ctx.F32[1], a, b));
}
Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
return DecorateNoContraction(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b));
return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b));
}
Id EmitFPNeg16(EmitContext& ctx, Id value) {
@@ -338,7 +338,7 @@ bool IsTextureInteger(EmitContext& ctx, const IR::TextureInstInfo& info) {
return ctx.textures.at(info.descriptor_index).is_integer;
}
Id DecorateRelaxedPrecision(EmitContext& ctx, IR::Inst* inst, Id sample) {
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) {
const auto info{inst->Flags<IR::TextureInstInfo>()};
if (info.relaxed_precision != 0) {
ctx.Decorate(sample, spv::Decoration::RelaxedPrecision);
@@ -351,14 +351,14 @@ Id Emit(MethodPtrType sparse_ptr, MethodPtrType non_sparse_ptr, EmitContext& ctx
Id result_type, Args&&... args) {
IR::Inst* const sparse{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
if (!sparse) {
return DecorateRelaxedPrecision(ctx, inst, (ctx.*non_sparse_ptr)(result_type, std::forward<Args>(args)...));
return Decorate(ctx, inst, (ctx.*non_sparse_ptr)(result_type, std::forward<Args>(args)...));
}
const Id struct_type{ctx.TypeStruct(ctx.U32[1], result_type)};
const Id sample{(ctx.*sparse_ptr)(struct_type, std::forward<Args>(args)...)};
const Id resident_code{ctx.OpCompositeExtract(ctx.U32[1], sample, 0U)};
sparse->SetDefinition(ctx.OpImageSparseTexelsResident(ctx.U1, resident_code));
sparse->Invalidate();
DecorateRelaxedPrecision(ctx, inst, sample);
Decorate(ctx, inst, sample);
return ctx.OpCompositeExtract(result_type, sample, 1U);
}
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -20,13 +17,14 @@ Id Image(EmitContext& ctx, IR::TextureInstInfo info) {
}
}
std::pair<Id, Id> AtomicImageArgs(EmitContext& ctx) {
std::pair<Id, Id> AtomicArgs(EmitContext& ctx) {
const Id scope{ctx.Const(static_cast<u32>(spv::Scope::Device))};
const Id semantics{ctx.u32_zero_value};
return {scope, semantics};
}
Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value, Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id value,
Id (Sirit::Module::*atomic_func)(Id, Id, Id, Id, Id)) {
if (!index.IsImmediate() || index.U32() != 0) {
// TODO: handle layers
throw NotImplementedException("Image indexing");
@@ -34,7 +32,7 @@ Id ImageAtomicU32(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
const auto info{inst->Flags<IR::TextureInstInfo>()};
const Id image{Image(ctx, info)};
const Id pointer{ctx.OpImageTexelPointer(ctx.image_u32, image, coords, ctx.Const(0U))};
const auto [scope, semantics] = AtomicImageArgs(ctx);
const auto [scope, semantics]{AtomicArgs(ctx)};
return (ctx.*atomic_func)(ctx.U32[1], pointer, scope, semantics, value);
}
} // Anonymous namespace
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -15,7 +12,7 @@
namespace Shader::Maxwell {
namespace {
union EncodingIBTT {
union Encoding {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> src_reg;
@@ -48,7 +45,7 @@ std::optional<u64> TrackLDC(Environment& env, Location block_begin, Location& po
std::optional<u64> TrackSHL(Environment& env, Location block_begin, Location& pos,
IR::Reg ldc_reg) {
return Track(env, block_begin, pos, [ldc_reg](u64 insn, Opcode opcode) {
const EncodingIBTT shl{insn};
const Encoding shl{insn};
return opcode == Opcode::SHL_imm && shl.dest_reg == ldc_reg;
});
}
@@ -56,7 +53,7 @@ std::optional<u64> TrackSHL(Environment& env, Location block_begin, Location& po
std::optional<u64> TrackIMNMX(Environment& env, Location block_begin, Location& pos,
IR::Reg shl_reg) {
return Track(env, block_begin, pos, [shl_reg](u64 insn, Opcode opcode) {
const EncodingIBTT imnmx{insn};
const Encoding imnmx{insn};
return opcode == Opcode::IMNMX_imm && imnmx.dest_reg == shl_reg;
});
}
@@ -69,8 +66,8 @@ std::optional<IndirectBranchTableInfo> TrackIndirectBranchTable(Environment& env
if (brx_opcode != Opcode::BRX && brx_opcode != Opcode::JMX) {
throw LogicError("Tracked instruction is not BRX or JMX");
}
const IR::Reg brx_reg{EncodingIBTT{brx_insn}.src_reg};
const s32 brx_offset{static_cast<s32>(EncodingIBTT{brx_insn}.brx_offset)};
const IR::Reg brx_reg{Encoding{brx_insn}.src_reg};
const s32 brx_offset{static_cast<s32>(Encoding{brx_insn}.brx_offset)};
Location pos{brx_pos};
const std::optional<u64> ldc_insn{TrackLDC(env, block_begin, pos, brx_reg)};
@@ -86,14 +83,14 @@ std::optional<IndirectBranchTableInfo> TrackIndirectBranchTable(Environment& env
if (!shl_insn) {
return std::nullopt;
}
const EncodingIBTT shl{*shl_insn};
const Encoding shl{*shl_insn};
const IR::Reg shl_reg{shl.src_reg};
const std::optional<u64> imnmx_insn{TrackIMNMX(env, block_begin, pos, shl_reg)};
if (!imnmx_insn) {
return std::nullopt;
}
const EncodingIBTT imnmx{*imnmx_insn};
const Encoding imnmx{*imnmx_insn};
if (imnmx.is_negative != 0) {
return std::nullopt;
}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
@@ -10,7 +10,7 @@
namespace Shader::Maxwell {
namespace {
enum class AtomicGlobalMemoryOp : u64 {
enum class AtomOp : u64 {
ADD,
MIN,
MAX,
@@ -32,33 +32,33 @@ enum class AtomSize : u64 {
S64,
};
IR::U32U64 ApplyIntegerAtomOp(IR::IREmitter& ir, const IR::U32U64& offset, const IR::U32U64& op_b, AtomicGlobalMemoryOp op, AtomSize size) {
IR::U32U64 ApplyIntegerAtomOp(IR::IREmitter& ir, const IR::U32U64& offset, const IR::U32U64& op_b, AtomOp op, AtomSize size) {
bool const is_signed = size == AtomSize::S64 || size == AtomSize::S32;
switch (op) {
case AtomicGlobalMemoryOp::ADD:
case AtomOp::ADD:
return ir.GlobalAtomicIAdd(offset, op_b);
case AtomicGlobalMemoryOp::MIN:
case AtomOp::MIN:
return ir.GlobalAtomicIMin(offset, op_b, is_signed);
case AtomicGlobalMemoryOp::MAX:
case AtomOp::MAX:
return ir.GlobalAtomicIMax(offset, op_b, is_signed);
case AtomicGlobalMemoryOp::INC:
case AtomOp::INC:
return ir.GlobalAtomicInc(offset, op_b);
case AtomicGlobalMemoryOp::DEC:
case AtomOp::DEC:
return ir.GlobalAtomicDec(offset, op_b);
case AtomicGlobalMemoryOp::AND:
case AtomOp::AND:
return ir.GlobalAtomicAnd(offset, op_b);
case AtomicGlobalMemoryOp::OR:
case AtomOp::OR:
return ir.GlobalAtomicOr(offset, op_b);
case AtomicGlobalMemoryOp::XOR:
case AtomOp::XOR:
return ir.GlobalAtomicXor(offset, op_b);
case AtomicGlobalMemoryOp::EXCH:
case AtomOp::EXCH:
return ir.GlobalAtomicExchange(offset, op_b);
default:
throw NotImplementedException("Integer Atom Operation {}", op);
}
}
IR::Value ApplyFpAtomOp(IR::IREmitter& ir, const IR::U64& offset, const IR::Value& op_b, AtomicGlobalMemoryOp op,
IR::Value ApplyFpAtomOp(IR::IREmitter& ir, const IR::U64& offset, const IR::Value& op_b, AtomOp op,
AtomSize size) {
static constexpr IR::FpControl f16_control{
.no_contraction = false,
@@ -71,12 +71,12 @@ IR::Value ApplyFpAtomOp(IR::IREmitter& ir, const IR::U64& offset, const IR::Valu
.fmz_mode = IR::FmzMode::FTZ,
};
switch (op) {
case AtomicGlobalMemoryOp::ADD:
case AtomOp::ADD:
return size == AtomSize::F32 ? ir.GlobalAtomicF32Add(offset, op_b, f32_control)
: ir.GlobalAtomicF16x2Add(offset, op_b, f16_control);
case AtomicGlobalMemoryOp::MIN:
case AtomOp::MIN:
return ir.GlobalAtomicF16x2Min(offset, op_b, f16_control);
case AtomicGlobalMemoryOp::MAX:
case AtomOp::MAX:
return ir.GlobalAtomicF16x2Max(offset, op_b, f16_control);
default:
throw NotImplementedException("FP Atom Operation {}", op);
@@ -112,19 +112,19 @@ IR::U64 AtomOffset(TranslatorVisitor& v, u64 insn) {
// ADD, INC, DEC for S64 does nothing
// Only ADD does something for F32
// Only ADD, MIN and MAX does something for F16x2
bool AtomOpNotApplicable(AtomSize size, AtomicGlobalMemoryOp op) {
bool AtomOpNotApplicable(AtomSize size, AtomOp op) {
// TODO: SAFEADD
switch (size) {
case AtomSize::U32:
case AtomSize::S32:
case AtomSize::U64:
return (op == AtomicGlobalMemoryOp::INC || op == AtomicGlobalMemoryOp::DEC);
return (op == AtomOp::INC || op == AtomOp::DEC);
case AtomSize::S64:
return (op == AtomicGlobalMemoryOp::ADD || op == AtomicGlobalMemoryOp::INC || op == AtomicGlobalMemoryOp::DEC);
return (op == AtomOp::ADD || op == AtomOp::INC || op == AtomOp::DEC);
case AtomSize::F32:
return op != AtomicGlobalMemoryOp::ADD;
return op != AtomOp::ADD;
case AtomSize::F16x2:
return !(op == AtomicGlobalMemoryOp::ADD || op == AtomicGlobalMemoryOp::MIN || op == AtomicGlobalMemoryOp::MAX);
return !(op == AtomOp::ADD || op == AtomOp::MIN || op == AtomOp::MAX);
default:
return false;
}
@@ -162,7 +162,7 @@ void StoreResult(TranslatorVisitor& v, IR::Reg dest_reg, const IR::Value& result
}
IR::Value ApplyAtomOp(TranslatorVisitor& v, IR::Reg operand_reg, const IR::U64& offset,
AtomSize size, AtomicGlobalMemoryOp op) {
AtomSize size, AtomOp op) {
switch (size) {
case AtomSize::U32:
case AtomSize::S32:
@@ -180,7 +180,7 @@ IR::Value ApplyAtomOp(TranslatorVisitor& v, IR::Reg operand_reg, const IR::U64&
}
void GlobalAtomic(TranslatorVisitor& v, IR::Reg dest_reg, IR::Reg operand_reg,
const IR::U64& offset, AtomSize size, AtomicGlobalMemoryOp op, bool write_dest) {
const IR::U64& offset, AtomSize size, AtomOp op, bool write_dest) {
IR::Value result = AtomOpNotApplicable(size, op)
? LoadGlobal(v.ir, offset, size)
: ApplyAtomOp(v, operand_reg, offset, size, op);
@@ -195,7 +195,7 @@ void TranslatorVisitor::ATOM(u64 insn) {
BitField<0, 8, IR::Reg> dest_reg;
BitField<20, 8, IR::Reg> operand_reg;
BitField<49, 3, AtomSize> size;
BitField<52, 4, AtomicGlobalMemoryOp> op;
BitField<52, 4, AtomOp> op;
} const atom{insn};
const IR::U64 offset{AtomOffset(*this, insn)};
GlobalAtomic(*this, atom.dest_reg, atom.operand_reg, offset, atom.size, atom.op, true);
@@ -206,7 +206,7 @@ void TranslatorVisitor::RED(u64 insn) {
u64 raw;
BitField<0, 8, IR::Reg> operand_reg;
BitField<20, 3, AtomSize> size;
BitField<23, 3, AtomicGlobalMemoryOp> op;
BitField<23, 3, AtomOp> op;
} const red{insn};
const IR::U64 offset{AtomOffset(*this, insn)};
GlobalAtomic(*this, IR::Reg::RZ, red.operand_reg, offset, red.size, red.op, true);
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,7 +7,7 @@
namespace Shader::Maxwell {
namespace {
enum class AtomicSharedMemoryOp : u64 {
enum class AtomOp : u64 {
ADD,
MIN,
MAX,
@@ -28,25 +25,26 @@ enum class AtomsSize : u64 {
U64,
};
IR::U32U64 ApplyAtomsOp(IR::IREmitter& ir, const IR::U32& offset, const IR::U32U64& op_b, AtomicSharedMemoryOp op, bool is_signed) {
IR::U32U64 ApplyAtomsOp(IR::IREmitter& ir, const IR::U32& offset, const IR::U32U64& op_b, AtomOp op,
bool is_signed) {
switch (op) {
case AtomicSharedMemoryOp::ADD:
case AtomOp::ADD:
return ir.SharedAtomicIAdd(offset, op_b);
case AtomicSharedMemoryOp::MIN:
case AtomOp::MIN:
return ir.SharedAtomicIMin(offset, op_b, is_signed);
case AtomicSharedMemoryOp::MAX:
case AtomOp::MAX:
return ir.SharedAtomicIMax(offset, op_b, is_signed);
case AtomicSharedMemoryOp::INC:
case AtomOp::INC:
return ir.SharedAtomicInc(offset, op_b);
case AtomicSharedMemoryOp::DEC:
case AtomOp::DEC:
return ir.SharedAtomicDec(offset, op_b);
case AtomicSharedMemoryOp::AND:
case AtomOp::AND:
return ir.SharedAtomicAnd(offset, op_b);
case AtomicSharedMemoryOp::OR:
case AtomOp::OR:
return ir.SharedAtomicOr(offset, op_b);
case AtomicSharedMemoryOp::XOR:
case AtomOp::XOR:
return ir.SharedAtomicXor(offset, op_b);
case AtomicSharedMemoryOp::EXCH:
case AtomOp::EXCH:
return ir.SharedAtomicExchange(offset, op_b);
default:
throw NotImplementedException("Integer Atoms Operation {}", op);
@@ -89,11 +87,11 @@ void TranslatorVisitor::ATOMS(u64 insn) {
BitField<8, 8, IR::Reg> addr_reg;
BitField<20, 8, IR::Reg> src_reg_b;
BitField<28, 2, AtomsSize> size;
BitField<52, 4, AtomicSharedMemoryOp> op;
BitField<52, 4, AtomOp> op;
} const atoms{insn};
const bool size_64{atoms.size == AtomsSize::U64};
if (size_64 && atoms.op != AtomicSharedMemoryOp::EXCH) {
if (size_64 && atoms.op != AtomOp::EXCH) {
throw NotImplementedException("64-bit Atoms Operation {}", atoms.op.Value());
}
const bool is_signed{atoms.size == AtomsSize::S32};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,7 +6,7 @@
namespace Shader::Maxwell {
namespace {
enum class FloatConversionFormat : u64 {
enum class FloatFormat : u64 {
F16 = 1,
F32 = 2,
F64 = 3,
@@ -24,13 +21,13 @@ enum class RoundingOp : u64 {
Trunc = 11,
};
[[nodiscard]] u32 WidthSize(FloatConversionFormat width) {
[[nodiscard]] u32 WidthSize(FloatFormat width) {
switch (width) {
case FloatConversionFormat::F16:
case FloatFormat::F16:
return 16;
case FloatConversionFormat::F32:
case FloatFormat::F32:
return 32;
case FloatConversionFormat::F64:
case FloatFormat::F64:
return 64;
default:
throw NotImplementedException("Invalid width {}", width);
@@ -47,8 +44,8 @@ void F2F(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a, bool abs) {
BitField<50, 1, u64> sat;
BitField<39, 4, u64> rounding_op;
BitField<39, 2, FpRounding> rounding;
BitField<10, 2, FloatConversionFormat> src_size;
BitField<8, 2, FloatConversionFormat> dst_size;
BitField<10, 2, FloatFormat> src_size;
BitField<8, 2, FloatFormat> dst_size;
[[nodiscard]] RoundingOp RoundingOperation() const {
constexpr u64 rounding_mask = 0x0B;
@@ -62,7 +59,7 @@ void F2F(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a, bool abs) {
IR::F16F32F64 input{v.ir.FPAbsNeg(src_a, abs, f2f.neg != 0)};
const bool any_fp64{f2f.src_size == FloatConversionFormat::F64 || f2f.dst_size == FloatConversionFormat::F64};
const bool any_fp64{f2f.src_size == FloatFormat::F64 || f2f.dst_size == FloatFormat::F64};
IR::FpControl fp_control{
.no_contraction = false,
.rounding = IR::FpRounding::DontCare,
@@ -77,13 +74,13 @@ void F2F(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a, bool abs) {
case RoundingOp::Pass:
// Make sure NANs are handled properly
switch (f2f.src_size) {
case FloatConversionFormat::F16:
case FloatFormat::F16:
input = v.ir.FPAdd(input, v.ir.FPConvert(16, v.ir.Imm32(0.0f)), fp_control);
break;
case FloatConversionFormat::F32:
case FloatFormat::F32:
input = v.ir.FPAdd(input, v.ir.Imm32(0.0f), fp_control);
break;
case FloatConversionFormat::F64:
case FloatFormat::F64:
input = v.ir.FPAdd(input, v.ir.Imm64(0.0), fp_control);
break;
}
@@ -109,15 +106,15 @@ void F2F(TranslatorVisitor& v, u64 insn, const IR::F16F32F64& src_a, bool abs) {
}
switch (f2f.dst_size) {
case FloatConversionFormat::F16: {
case FloatFormat::F16: {
const IR::F16 imm{v.ir.FPConvert(16, v.ir.Imm32(0.0f))};
v.X(f2f.dest_reg, v.ir.PackFloat2x16(v.ir.CompositeConstruct(input, imm)));
break;
}
case FloatConversionFormat::F32:
case FloatFormat::F32:
v.F(f2f.dest_reg, input);
break;
case FloatConversionFormat::F64:
case FloatFormat::F64:
v.D(f2f.dest_reg, input);
break;
default:
@@ -130,21 +127,21 @@ void TranslatorVisitor::F2F_reg(u64 insn) {
union {
u64 insn;
BitField<49, 1, u64> abs;
BitField<10, 2, FloatConversionFormat> src_size;
BitField<10, 2, FloatFormat> src_size;
BitField<41, 1, u64> selector;
} const f2f{insn};
IR::F16F32F64 src_a;
switch (f2f.src_size) {
case FloatConversionFormat::F16: {
case FloatFormat::F16: {
auto [lhs_a, rhs_a]{Extract(ir, GetReg20(insn), Swizzle::H1_H0)};
src_a = f2f.selector != 0 ? rhs_a : lhs_a;
break;
}
case FloatConversionFormat::F32:
case FloatFormat::F32:
src_a = GetFloatReg20(insn);
break;
case FloatConversionFormat::F64:
case FloatFormat::F64:
src_a = GetDoubleReg20(insn);
break;
default:
@@ -157,21 +154,21 @@ void TranslatorVisitor::F2F_cbuf(u64 insn) {
union {
u64 insn;
BitField<49, 1, u64> abs;
BitField<10, 2, FloatConversionFormat> src_size;
BitField<10, 2, FloatFormat> src_size;
BitField<41, 1, u64> selector;
} const f2f{insn};
IR::F16F32F64 src_a;
switch (f2f.src_size) {
case FloatConversionFormat::F16: {
case FloatFormat::F16: {
auto [lhs_a, rhs_a]{Extract(ir, GetCbuf(insn), Swizzle::H1_H0)};
src_a = f2f.selector != 0 ? rhs_a : lhs_a;
break;
}
case FloatConversionFormat::F32:
case FloatFormat::F32:
src_a = GetFloatCbuf(insn);
break;
case FloatConversionFormat::F64:
case FloatFormat::F64:
src_a = GetDoubleCbuf(insn);
break;
default:
@@ -184,7 +181,7 @@ void TranslatorVisitor::F2F_imm([[maybe_unused]] u64 insn) {
union {
u64 insn;
BitField<49, 1, u64> abs;
BitField<10, 2, FloatConversionFormat> src_size;
BitField<10, 2, FloatFormat> src_size;
BitField<41, 1, u64> selector;
BitField<20, 19, u64> imm;
BitField<56, 1, u64> imm_neg;
@@ -192,7 +189,7 @@ void TranslatorVisitor::F2F_imm([[maybe_unused]] u64 insn) {
IR::F16F32F64 src_a;
switch (f2f.src_size) {
case FloatConversionFormat::F16: {
case FloatFormat::F16: {
const u32 imm{static_cast<u32>(f2f.imm & 0x0000ffff)};
const IR::Value vector{ir.UnpackFloat2x16(ir.Imm32(imm | (imm << 16)))};
src_a = IR::F16{ir.CompositeExtract(vector, f2f.selector != 0 ? 0 : 1)};
@@ -201,10 +198,10 @@ void TranslatorVisitor::F2F_imm([[maybe_unused]] u64 insn) {
}
break;
}
case FloatConversionFormat::F32:
case FloatFormat::F32:
src_a = GetFloatImm20(insn);
break;
case FloatConversionFormat::F64:
case FloatFormat::F64:
src_a = GetDoubleImm20(insn);
break;
default:
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,7 +7,7 @@
namespace Shader::Maxwell {
namespace {
enum class FPReduceMode : u64 {
enum class Mode : u64 {
SINCOS,
EX2,
};
@@ -19,7 +16,7 @@ void RRO(TranslatorVisitor& v, u64 insn, const IR::F32& src) {
union {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
BitField<39, 1, FPReduceMode> mode;
BitField<39, 1, Mode> mode;
BitField<45, 1, u64> neg;
BitField<49, 1, u64> abs;
} const rro{insn};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,48 +7,48 @@
namespace Shader::Maxwell {
namespace {
enum class IADD3Shift : u64 {
enum class Shift : u64 {
None,
Right,
Left,
};
enum class IADD3Half : u64 {
enum class Half : u64 {
All,
Lower,
Upper,
};
[[nodiscard]] IR::U32 IntegerHalf(IR::IREmitter& ir, const IR::U32& value, IADD3Half half) {
[[nodiscard]] IR::U32 IntegerHalf(IR::IREmitter& ir, const IR::U32& value, Half half) {
constexpr bool is_signed{false};
switch (half) {
case IADD3Half::All:
case Half::All:
return value;
case IADD3Half::Lower:
case Half::Lower:
return ir.BitFieldExtract(value, ir.Imm32(0), ir.Imm32(16), is_signed);
case IADD3Half::Upper:
case Half::Upper:
return ir.BitFieldExtract(value, ir.Imm32(16), ir.Imm32(16), is_signed);
}
throw NotImplementedException("Invalid half");
}
[[nodiscard]] IR::U32 IntegerShift(IR::IREmitter& ir, const IR::U32& value, IADD3Shift shift) {
[[nodiscard]] IR::U32 IntegerShift(IR::IREmitter& ir, const IR::U32& value, Shift shift) {
switch (shift) {
case IADD3Shift::None:
case Shift::None:
return value;
case IADD3Shift::Right: {
case Shift::Right: {
// 33-bit RS IADD3 edge case
const IR::U1 edge_case{ir.GetCarryFromOp(value)};
const IR::U32 shifted{ir.ShiftRightLogical(value, ir.Imm32(16))};
return IR::U32{ir.Select(edge_case, ir.IAdd(shifted, ir.Imm32(0x10000)), shifted)};
}
case IADD3Shift::Left:
case Shift::Left:
return ir.ShiftLeftLogical(value, ir.Imm32(16));
}
throw NotImplementedException("Invalid shift");
}
void IADD3(TranslatorVisitor& v, u64 insn, IR::U32 op_a, IR::U32 op_b, IR::U32 op_c,
IADD3Shift shift = IADD3Shift::None) {
Shift shift = Shift::None) {
union {
u64 insn;
BitField<0, 8, IR::Reg> dest_reg;
@@ -74,7 +71,7 @@ void IADD3(TranslatorVisitor& v, u64 insn, IR::U32 op_a, IR::U32 op_b, IR::U32 o
IR::U32 lhs_1{v.ir.IAdd(op_a, op_b)};
if (iadd3.x != 0) {
// TODO: How does RS behave when X is set?
if (shift == IADD3Shift::Right) {
if (shift == Shift::Right) {
throw NotImplementedException("IADD3 X+RS");
}
const IR::U32 carry{v.ir.Select(v.ir.GetCFlag(), v.ir.Imm32(1), v.ir.Imm32(0))};
@@ -101,10 +98,10 @@ void IADD3(TranslatorVisitor& v, u64 insn, IR::U32 op_a, IR::U32 op_b, IR::U32 o
void TranslatorVisitor::IADD3_reg(u64 insn) {
union {
u64 insn;
BitField<37, 2, IADD3Shift> shift;
BitField<35, 2, IADD3Half> half_a;
BitField<33, 2, IADD3Half> half_b;
BitField<31, 2, IADD3Half> half_c;
BitField<37, 2, Shift> shift;
BitField<35, 2, Half> half_a;
BitField<33, 2, Half> half_b;
BitField<31, 2, Half> half_c;
} const iadd3{insn};
const auto op_a{IntegerHalf(ir, GetReg8(insn), iadd3.half_a)};
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
@@ -11,7 +11,7 @@
namespace Shader::Maxwell {
namespace {
enum class IntegerToFloatFormat : u64 {
enum class FloatFormat : u64 {
F16 = 1,
F32 = 2,
F64 = 3,
@@ -24,10 +24,10 @@ enum class IntFormat : u64 {
U64 = 3,
};
union EncodingIFPC {
union Encoding {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 2, IntegerToFloatFormat> float_format;
BitField<8, 2, FloatFormat> float_format;
BitField<10, 2, IntFormat> int_format;
BitField<13, 1, u64> is_signed;
BitField<39, 2, FpRounding> fp_rounding;
@@ -38,16 +38,16 @@ union EncodingIFPC {
};
bool Is64(u64 insn) {
return EncodingIFPC{insn}.int_format == IntFormat::U64;
return Encoding{insn}.int_format == IntFormat::U64;
}
int BitSize(IntegerToFloatFormat format) {
int BitSize(FloatFormat format) {
switch (format) {
case IntegerToFloatFormat::F16:
case FloatFormat::F16:
return 16;
case IntegerToFloatFormat::F32:
case FloatFormat::F32:
return 32;
case IntegerToFloatFormat::F64:
case FloatFormat::F64:
return 64;
}
throw NotImplementedException("Invalid float format {}", format);
@@ -62,7 +62,7 @@ IR::U32 SmallAbs(TranslatorVisitor& v, const IR::U32& value, int bitsize) {
}
void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
const EncodingIFPC i2f{insn};
const Encoding i2f{insn};
if (i2f.cc != 0) {
throw NotImplementedException("I2F CC");
}
@@ -119,15 +119,15 @@ void I2F(TranslatorVisitor& v, u64 insn, IR::U32U64 src) {
}
}
switch (i2f.float_format) {
case IntegerToFloatFormat::F16: {
case FloatFormat::F16: {
const IR::F16 zero{v.ir.FPConvert(16, v.ir.Imm32(0.0f))};
v.X(i2f.dest_reg, v.ir.PackFloat2x16(v.ir.CompositeConstruct(value, zero)));
break;
}
case IntegerToFloatFormat::F32:
case FloatFormat::F32:
v.F(i2f.dest_reg, value);
break;
case IntegerToFloatFormat::F64: {
case FloatFormat::F64: {
if (!IR::IsAligned(i2f.dest_reg, 2)) {
throw NotImplementedException("Unaligned destination {}", i2f.dest_reg.Value());
}
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -18,18 +15,18 @@ enum class SelectMode : u64 {
CBCC,
};
enum class IMADHalf : u64 {
enum class Half : u64 {
H0, // Least-significant bits (15:0)
H1, // Most-significant bits (31:16)
};
IR::U32 ExtractHalf(TranslatorVisitor& v, const IR::U32& src, IMADHalf half, bool is_signed) {
const IR::U32 offset{v.ir.Imm32(half == IMADHalf::H1 ? 16 : 0)};
IR::U32 ExtractHalf(TranslatorVisitor& v, const IR::U32& src, Half half, bool is_signed) {
const IR::U32 offset{v.ir.Imm32(half == Half::H1 ? 16 : 0)};
return v.ir.BitFieldExtract(src, offset, v.ir.Imm32(16), is_signed);
}
void XMAD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& src_c,
SelectMode select_mode, IMADHalf half_b, bool psl, bool mrg, bool x) {
SelectMode select_mode, Half half_b, bool psl, bool mrg, bool x) {
union {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
@@ -37,7 +34,7 @@ void XMAD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& s
BitField<47, 1, u64> cc;
BitField<48, 1, u64> is_a_signed;
BitField<49, 1, u64> is_b_signed;
BitField<53, 1, IMADHalf> half_a;
BitField<53, 1, Half> half_a;
} const xmad{insn};
if (x) {
@@ -56,9 +53,9 @@ void XMAD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& s
case SelectMode::Default:
return src_c;
case SelectMode::CLO:
return ExtractHalf(v, src_c, IMADHalf::H0, false);
return ExtractHalf(v, src_c, Half::H0, false);
case SelectMode::CHI:
return ExtractHalf(v, src_c, IMADHalf::H1, false);
return ExtractHalf(v, src_c, Half::H1, false);
case SelectMode::CBCC:
return v.ir.IAdd(v.ir.ShiftLeftLogical(src_b, v.ir.Imm32(16)), src_c);
case SelectMode::CSFU:
@@ -69,7 +66,7 @@ void XMAD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& s
IR::U32 result{v.ir.IAdd(product, op_c)};
if (mrg) {
// .MRG inserts src_b [15:0] into result's [31:16].
const IR::U32 lsb_b{ExtractHalf(v, src_b, IMADHalf::H0, false)};
const IR::U32 lsb_b{ExtractHalf(v, src_b, Half::H0, false)};
result = v.ir.BitFieldInsert(result, lsb_b, v.ir.Imm32(16), v.ir.Imm32(16));
}
if (xmad.cc) {
@@ -83,7 +80,7 @@ void XMAD(TranslatorVisitor& v, u64 insn, const IR::U32& src_b, const IR::U32& s
void TranslatorVisitor::XMAD_reg(u64 insn) {
union {
u64 raw;
BitField<35, 1, IMADHalf> half_b;
BitField<35, 1, Half> half_b;
BitField<36, 1, u64> psl;
BitField<37, 1, u64> mrg;
BitField<38, 1, u64> x;
@@ -98,7 +95,7 @@ void TranslatorVisitor::XMAD_rc(u64 insn) {
union {
u64 raw;
BitField<50, 2, SelectMode> select_mode;
BitField<52, 1, IMADHalf> half_b;
BitField<52, 1, Half> half_b;
BitField<54, 1, u64> x;
} const xmad{insn};
@@ -110,7 +107,7 @@ void TranslatorVisitor::XMAD_cr(u64 insn) {
union {
u64 raw;
BitField<50, 2, SelectMode> select_mode;
BitField<52, 1, IMADHalf> half_b;
BitField<52, 1, Half> half_b;
BitField<54, 1, u64> x;
BitField<55, 1, u64> psl;
BitField<56, 1, u64> mrg;
@@ -131,7 +128,7 @@ void TranslatorVisitor::XMAD_imm(u64 insn) {
} const xmad{insn};
XMAD(*this, insn, ir.Imm32(static_cast<u32>(xmad.src_b)), GetReg39(insn), xmad.select_mode,
IMADHalf::H0, xmad.psl != 0, xmad.mrg != 0, xmad.x != 0);
Half::H0, xmad.psl != 0, xmad.mrg != 0, xmad.x != 0);
}
} // namespace Shader::Maxwell
@@ -10,7 +10,7 @@
namespace Shader::Maxwell {
namespace {
enum class ISBERDMode : u64 {
enum class Mode : u64 {
Default,
Patch,
Prim,
@@ -24,17 +24,17 @@ enum class SZ : u64 {
F32
};
enum class ISBERDShift : u64 {
enum class Shift : u64 {
Default,
U16,
B32,
};
IR::U32 scaleIndex(IR::IREmitter& ir, IR::U32 index, ISBERDShift shift) {
IR::U32 scaleIndex(IR::IREmitter& ir, IR::U32 index, Shift shift) {
switch (shift) {
case ISBERDShift::Default: return index;
case ISBERDShift::U16: return ir.ShiftLeftLogical(index, ir.Imm32(1));
case ISBERDShift::B32: return ir.ShiftLeftLogical(index, ir.Imm32(2));
case Shift::Default: return index;
case Shift::U16: return ir.ShiftLeftLogical(index, ir.Imm32(1));
case Shift::B32: return ir.ShiftLeftLogical(index, ir.Imm32(2));
default: UNREACHABLE();
}
}
@@ -63,9 +63,9 @@ void TranslatorVisitor::ISBERD(u64 insn) {
BitField<24, 8, u32> imm;
BitField<31, 1, u64> skew;
BitField<32, 1, u64> o;
BitField<33, 2, ISBERDMode> mode;
BitField<33, 2, Mode> mode;
BitField<36, 4, SZ> sz;
BitField<47, 2, ISBERDShift> shift;
BitField<47, 2, Shift> shift;
} const isberd{insn};
IR::U32 index{};
@@ -95,18 +95,18 @@ void TranslatorVisitor::ISBERD(u64 insn) {
return;
}
if (isberd.mode.Value() != ISBERDMode::Default) {
if (isberd.mode.Value() != Mode::Default) {
if (isberd.skew.Value()) {
index = ir.IAdd(index, skewBytes(ir, SZ::U32));
}
IR::F32 float_index{};
switch (isberd.mode.Value()) {
case ISBERDMode::Patch: float_index = ir.GetPatch(index.Patch());
case Mode::Patch: float_index = ir.GetPatch(index.Patch());
break;
case ISBERDMode::Prim: float_index = ir.GetAttribute(index.Attribute());
case Mode::Prim: float_index = ir.GetAttribute(index.Attribute());
break;
case ISBERDMode::Attr: float_index = ir.GetAttributeIndexed(index);
case Mode::Attr: float_index = ir.GetAttributeIndexed(index);
break;
default: UNREACHABLE();
}
@@ -12,7 +12,7 @@
namespace Shader::Maxwell {
namespace {
enum class InterpolationSize : u64 {
enum class Size : u64 {
B32,
B64,
B96,
@@ -32,15 +32,15 @@ enum class SampleMode : u64 {
Offset,
};
u32 NumElements(InterpolationSize size) {
u32 NumElements(Size size) {
switch (size) {
case InterpolationSize::B32:
case Size::B32:
return 1;
case InterpolationSize::B64:
case Size::B64:
return 2;
case InterpolationSize::B96:
case Size::B96:
return 3;
case InterpolationSize::B128:
case Size::B128:
return 4;
}
throw InvalidArgument("Invalid size {}", size);
@@ -68,7 +68,7 @@ void TranslatorVisitor::ALD(u64 insn) {
BitField<39, 8, IR::Reg> vertex_reg;
BitField<32, 1, u64> o;
BitField<31, 1, u64> patch;
BitField<47, 2, InterpolationSize> size;
BitField<47, 2, Size> size;
} const ald{insn};
const u64 offset{ald.absolute_offset.Value()};
@@ -106,7 +106,7 @@ void TranslatorVisitor::AST(u64 insn) {
BitField<20, 11, s64> relative_offset;
BitField<31, 1, u64> patch;
BitField<39, 8, IR::Reg> vertex_reg;
BitField<47, 2, InterpolationSize> size;
BitField<47, 2, Size> size;
} const ast{insn};
if (ast.index_reg != IR::Reg::RZ) {
@@ -10,7 +10,7 @@
namespace Shader::Maxwell {
namespace {
enum class LoadStoreLocalSharedSize : u64 {
enum class Size : u64 {
U8,
S8,
U16,
@@ -48,23 +48,23 @@ std::pair<IR::U32, IR::U32> WordOffset(TranslatorVisitor& v, u64 insn) {
std::pair<int, bool> GetSize(u64 insn) {
union {
u64 raw;
BitField<48, 3, LoadStoreLocalSharedSize> size;
BitField<48, 3, Size> size;
} const encoding{insn};
switch (encoding.size) {
case LoadStoreLocalSharedSize::U8:
case Size::U8:
return {8, false};
case LoadStoreLocalSharedSize::S8:
case Size::S8:
return {8, true};
case LoadStoreLocalSharedSize::U16:
case Size::U16:
return {16, false};
case LoadStoreLocalSharedSize::S16:
case Size::S16:
return {16, true};
case LoadStoreLocalSharedSize::B32:
case Size::B32:
return {32, false};
case LoadStoreLocalSharedSize::B64:
case Size::B64:
return {64, false};
case LoadStoreLocalSharedSize::B128:
case Size::B128:
return {128, false};
default:
throw NotImplementedException("Invalid size {}", encoding.size.Value());
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -33,7 +30,7 @@ enum class StoreSize : u64 {
};
// See Table 27 in https://docs.nvidia.com/cuda/parallel-thread-execution/index.html
enum class XMEMLoadCache : u64 {
enum class LoadCache : u64 {
CA, // Cache at all levels, likely to be accessed again
CG, // Cache at global level (cache in L2 and below, not L1)
CI, // ???
@@ -41,7 +38,7 @@ enum class XMEMLoadCache : u64 {
};
// See Table 28 in https://docs.nvidia.com/cuda/parallel-thread-execution/index.html
enum class XMEMStoreCache : u64 {
enum class StoreCache : u64 {
WB, // Cache write-back all coherent levels
CG, // Cache at global level
CS, // Cache streaming, likely to be accessed once
@@ -86,7 +83,7 @@ void TranslatorVisitor::LDG(u64 insn) {
union {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
BitField<46, 2, XMEMLoadCache> cache;
BitField<46, 2, LoadCache> cache;
BitField<48, 3, LoadSize> size;
} const ldg{insn};
@@ -140,7 +137,7 @@ void TranslatorVisitor::STG(u64 insn) {
union {
u64 raw;
BitField<0, 8, IR::Reg> data_reg;
BitField<46, 2, XMEMStoreCache> cache;
BitField<46, 2, StoreCache> cache;
BitField<48, 3, StoreSize> size;
} const stg{insn};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,7 +7,7 @@
namespace Shader::Maxwell {
namespace {
enum class MovePredicateFlagMode : u64 {
enum class Mode : u64 {
PR,
CC,
};
@@ -29,12 +26,12 @@ void TranslatorVisitor::P2R_imm(u64 insn) {
u64 raw;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> src;
BitField<40, 1, MovePredicateFlagMode> mode;
BitField<40, 1, Mode> mode;
BitField<41, 2, u64> byte_selector;
} const p2r{insn};
const u32 mask{GetImm20(insn).U32()};
const bool pr_mode{p2r.mode == MovePredicateFlagMode::PR};
const bool pr_mode{p2r.mode == Mode::PR};
const u32 num_items{pr_mode ? 7U : 4U};
const u32 offset{static_cast<u32>(p2r.byte_selector) * 8};
IR::U32 insert{ir.Imm32(0)};
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,7 +7,7 @@
namespace Shader::Maxwell {
namespace {
enum class PredicateFlagMode : u64 {
enum class Mode : u64 {
PR,
CC,
};
@@ -34,12 +31,12 @@ void R2P(TranslatorVisitor& v, u64 insn, const IR::U32& mask) {
union {
u64 raw;
BitField<8, 8, IR::Reg> src_reg;
BitField<40, 1, PredicateFlagMode> mode;
BitField<40, 1, Mode> mode;
BitField<41, 2, u64> byte_selector;
} const r2p{insn};
const IR::U32 src{v.X(r2p.src_reg)};
const IR::U32 count{v.ir.Imm32(1)};
const bool pr_mode{r2p.mode == PredicateFlagMode::PR};
const bool pr_mode{r2p.mode == Mode::PR};
const u32 num_items{pr_mode ? 7U : 4U};
const u32 offset_base{static_cast<u32>(r2p.byte_selector) * 8};
for (u32 index = 0; index < num_items; ++index) {
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,7 +7,7 @@
namespace Shader::Maxwell {
namespace {
enum class PixelLoadMode : u64 {
enum class Mode : u64 {
Default,
CovMask,
Covered,
@@ -23,7 +20,7 @@ enum class PixelLoadMode : u64 {
void TranslatorVisitor::PIXLD(u64 insn) {
union {
u64 raw;
BitField<31, 3, PixelLoadMode> mode;
BitField<31, 3, Mode> mode;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> addr_reg;
BitField<20, 8, s64> addr_offset;
@@ -37,11 +34,11 @@ void TranslatorVisitor::PIXLD(u64 insn) {
throw NotImplementedException("Non-zero source register");
}
switch (pixld.mode) {
case PixelLoadMode::MyIndex:
case Mode::MyIndex:
X(pixld.dest_reg, ir.SampleId());
break;
default:
throw NotImplementedException("PixelLoadMode {}", pixld.mode.Value());
throw NotImplementedException("Mode {}", pixld.mode.Value());
}
}
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
@@ -11,7 +11,7 @@
namespace Shader::Maxwell {
namespace {
enum class SurfaceAtomicType : u64 {
enum class Type : u64 {
_1D = 0,
_1D_BUFFER = 1,
_1D_ARRAY = 2,
@@ -25,7 +25,7 @@ enum class SurfaceAtomicType : u64 {
/// For any would be newcomer to here: Yes - GPU dissasembly says S64 should
/// be after F16x2FTZRN. However if you do plan to revert this, you MUST test
/// ToTK beforehand. As the game will break with the subtle change
enum class SurfaceAtomicSize : u64 {
enum class Size : u64 {
U32,
S32,
U64,
@@ -48,46 +48,46 @@ enum class AtomicOp : u64 {
EXCH,
};
enum class SurfaceAtomicClamp : u64 {
enum class Clamp : u64 {
IGN,
Default,
TRAP,
};
TextureType GetType(SurfaceAtomicType type) {
TextureType GetType(Type type) {
switch (type) {
case SurfaceAtomicType::_1D:
case Type::_1D:
return TextureType::Color1D;
case SurfaceAtomicType::_1D_BUFFER:
case Type::_1D_BUFFER:
return TextureType::Buffer;
case SurfaceAtomicType::_1D_ARRAY:
case Type::_1D_ARRAY:
return TextureType::ColorArray1D;
case SurfaceAtomicType::_2D:
case Type::_2D:
return TextureType::Color2D;
case SurfaceAtomicType::_2D_ARRAY:
case Type::_2D_ARRAY:
return TextureType::ColorArray2D;
case SurfaceAtomicType::_3D:
case Type::_3D:
return TextureType::Color3D;
default:
throw NotImplementedException("Invalid type {}", type);
}
}
IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, SurfaceAtomicType type) {
IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, Type type) {
const auto array{[&](int index) {
return v.ir.BitFieldExtract(v.X(reg + index), v.ir.Imm32(0), v.ir.Imm32(16));
}};
switch (type) {
case SurfaceAtomicType::_1D:
case SurfaceAtomicType::_1D_BUFFER:
case Type::_1D:
case Type::_1D_BUFFER:
return v.X(reg);
case SurfaceAtomicType::_1D_ARRAY:
case Type::_1D_ARRAY:
return v.ir.CompositeConstruct(v.X(reg), array(1));
case SurfaceAtomicType::_2D:
case Type::_2D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1));
case SurfaceAtomicType::_2D_ARRAY:
case Type::_2D_ARRAY:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), array(2));
case SurfaceAtomicType::_3D:
case Type::_3D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), v.X(reg + 2));
default:
throw NotImplementedException("Invalid type {}", type);
@@ -121,11 +121,11 @@ IR::Value ApplyAtomicOp(IR::IREmitter& ir, const IR::U32& handle, const IR::Valu
}
}
ImageFormat Format(SurfaceAtomicSize size) {
ImageFormat Format(Size size) {
switch (size) {
case SurfaceAtomicSize::U32:
case SurfaceAtomicSize::S32:
case SurfaceAtomicSize::SD32:
case Size::U32:
case Size::S32:
case Size::SD32:
return ImageFormat::R32_UINT;
default:
break;
@@ -133,11 +133,11 @@ ImageFormat Format(SurfaceAtomicSize size) {
throw NotImplementedException("Invalid size {}", size);
}
bool IsSizeInt32(SurfaceAtomicSize size) {
bool IsSizeInt32(Size size) {
switch (size) {
case SurfaceAtomicSize::U32:
case SurfaceAtomicSize::S32:
case SurfaceAtomicSize::SD32:
case Size::U32:
case Size::S32:
case Size::SD32:
return true;
default:
return false;
@@ -145,15 +145,15 @@ bool IsSizeInt32(SurfaceAtomicSize size) {
}
void ImageAtomOp(TranslatorVisitor& v, IR::Reg dest_reg, IR::Reg operand_reg, IR::Reg coord_reg,
std::optional<IR::Reg> bindless_reg, AtomicOp op, SurfaceAtomicClamp clamp, SurfaceAtomicSize size, SurfaceAtomicType type,
std::optional<IR::Reg> bindless_reg, AtomicOp op, Clamp clamp, Size size, Type type,
u64 bound_offset, bool is_bindless, bool write_result) {
if (clamp != SurfaceAtomicClamp::IGN) {
throw NotImplementedException("SurfaceAtomicClamp {}", clamp);
if (clamp != Clamp::IGN) {
throw NotImplementedException("Clamp {}", clamp);
}
if (!IsSizeInt32(size)) {
throw NotImplementedException("SurfaceAtomicSize {}", size);
throw NotImplementedException("Size {}", size);
}
const bool is_signed{size == SurfaceAtomicSize::S32};
const bool is_signed{size == Size::S32};
const ImageFormat format{Format(size)};
const TextureType tex_type{GetType(type)};
const IR::Value coords{MakeCoords(v, coord_reg, type)};
@@ -178,9 +178,9 @@ void TranslatorVisitor::SUATOM(u64 insn) {
u64 raw;
BitField<54, 1, u64> is_bindless;
BitField<29, 4, AtomicOp> op;
BitField<33, 3, SurfaceAtomicType> type;
BitField<51, 3, SurfaceAtomicSize> size;
BitField<49, 2, SurfaceAtomicClamp> clamp;
BitField<33, 3, Type> type;
BitField<51, 3, Size> size;
BitField<49, 2, Clamp> clamp;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> coord_reg;
BitField<20, 8, IR::Reg> operand_reg;
@@ -199,9 +199,9 @@ void TranslatorVisitor::SURED(u64 insn) {
u64 raw;
BitField<51, 1, u64> is_bound;
BitField<24, 3, AtomicOp> op; //OK - 24 (SURedOp)
BitField<33, 3, SurfaceAtomicType> type; //OK? - 33 (Dim)
BitField<20, 3, SurfaceAtomicSize> size; //?
BitField<49, 2, SurfaceAtomicClamp> clamp; //OK - 49 (Clamp4)
BitField<33, 3, Type> type; //OK? - 33 (Dim)
BitField<20, 3, Size> size; //?
BitField<49, 2, Clamp> clamp; //OK - 49 (Clamp4)
BitField<0, 8, IR::Reg> operand_reg; //RA?
BitField<8, 8, IR::Reg> coord_reg; //RB?
BitField<36, 13, u64> bound_offset; //OK 33 (TidB)
@@ -1,6 +1,3 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -14,7 +11,7 @@
namespace Shader::Maxwell {
namespace {
enum class SurfaceLoadStoreType : u64 {
enum class Type : u64 {
_1D,
BUFFER_1D,
ARRAY_1D,
@@ -23,31 +20,31 @@ enum class SurfaceLoadStoreType : u64 {
_3D,
};
constexpr unsigned SHADER_R = 1 << 0;
constexpr unsigned SHADER_G = 1 << 1;
constexpr unsigned SHADER_B = 1 << 2;
constexpr unsigned SHADER_A = 1 << 3;
constexpr unsigned R = 1 << 0;
constexpr unsigned G = 1 << 1;
constexpr unsigned B = 1 << 2;
constexpr unsigned A = 1 << 3;
constexpr std::array MASK{
0U, //
SHADER_R, //
SHADER_G, //
SHADER_R | SHADER_G, //
SHADER_B, //
SHADER_R | SHADER_B, //
SHADER_G | SHADER_B, //
SHADER_R | SHADER_G | SHADER_B, //
SHADER_A, //
SHADER_R | SHADER_A, //
SHADER_G | SHADER_A, //
SHADER_R | SHADER_G | SHADER_A, //
SHADER_B | SHADER_A, //
SHADER_R | SHADER_B | SHADER_A, //
SHADER_G | SHADER_B | SHADER_A, //
SHADER_R | SHADER_G | SHADER_B | SHADER_A, //
R, //
G, //
R | G, //
B, //
R | B, //
G | B, //
R | G | B, //
A, //
R | A, //
G | A, //
R | G | A, //
B | A, //
R | B | A, //
G | B | A, //
R | G | B | A, //
};
enum class SurfaceLoadStoreSize : u64 {
enum class Size : u64 {
U8,
S8,
U16,
@@ -57,96 +54,96 @@ enum class SurfaceLoadStoreSize : u64 {
B128,
};
enum class SurfaceLoadStoreClamp : u64 {
enum class Clamp : u64 {
IGN,
Default,
TRAP,
};
// https://docs.nvidia.com/cuda/parallel-thread-execution/index.html#cache-operators
enum class SURFLoadCache : u64 {
enum class LoadCache : u64 {
CA, // Cache at all levels, likely to be accessed again
CG, // Cache at global level (L2 and below, not L1)
CI, // ???
CV, // Don't cache and fetch again (volatile)
};
enum class SURFStoreCache : u64 {
enum class StoreCache : u64 {
WB, // Cache write-back all coherent levels
CG, // Cache at global level (L2 and below, not L1)
CS, // Cache streaming, likely to be accessed once
WT, // Cache write-through (to system memory, volatile?)
};
ImageFormat Format(SurfaceLoadStoreSize size) {
ImageFormat Format(Size size) {
switch (size) {
case SurfaceLoadStoreSize::U8:
case Size::U8:
return ImageFormat::R8_UINT;
case SurfaceLoadStoreSize::S8:
case Size::S8:
return ImageFormat::R8_SINT;
case SurfaceLoadStoreSize::U16:
case Size::U16:
return ImageFormat::R16_UINT;
case SurfaceLoadStoreSize::S16:
case Size::S16:
return ImageFormat::R16_SINT;
case SurfaceLoadStoreSize::B32:
case Size::B32:
return ImageFormat::R32_UINT;
case SurfaceLoadStoreSize::B64:
case Size::B64:
return ImageFormat::R32G32_UINT;
case SurfaceLoadStoreSize::B128:
case Size::B128:
return ImageFormat::R32G32B32A32_UINT;
}
throw NotImplementedException("Invalid size {}", size);
}
int SizeInRegs(SurfaceLoadStoreSize size) {
int SizeInRegs(Size size) {
switch (size) {
case SurfaceLoadStoreSize::U8:
case SurfaceLoadStoreSize::S8:
case SurfaceLoadStoreSize::U16:
case SurfaceLoadStoreSize::S16:
case SurfaceLoadStoreSize::B32:
case Size::U8:
case Size::S8:
case Size::U16:
case Size::S16:
case Size::B32:
return 1;
case SurfaceLoadStoreSize::B64:
case Size::B64:
return 2;
case SurfaceLoadStoreSize::B128:
case Size::B128:
return 4;
}
throw NotImplementedException("Invalid size {}", size);
}
TextureType GetType(SurfaceLoadStoreType type) {
TextureType GetType(Type type) {
switch (type) {
case SurfaceLoadStoreType::_1D:
case Type::_1D:
return TextureType::Color1D;
case SurfaceLoadStoreType::BUFFER_1D:
case Type::BUFFER_1D:
return TextureType::Buffer;
case SurfaceLoadStoreType::ARRAY_1D:
case Type::ARRAY_1D:
return TextureType::ColorArray1D;
case SurfaceLoadStoreType::_2D:
case Type::_2D:
return TextureType::Color2D;
case SurfaceLoadStoreType::ARRAY_2D:
case Type::ARRAY_2D:
return TextureType::ColorArray2D;
case SurfaceLoadStoreType::_3D:
case Type::_3D:
return TextureType::Color3D;
}
throw NotImplementedException("Invalid type {}", type);
}
IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, SurfaceLoadStoreType type) {
IR::Value MakeCoords(TranslatorVisitor& v, IR::Reg reg, Type type) {
const auto array{[&](int index) {
return v.ir.BitFieldExtract(v.X(reg + index), v.ir.Imm32(0), v.ir.Imm32(16));
}};
switch (type) {
case SurfaceLoadStoreType::_1D:
case SurfaceLoadStoreType::BUFFER_1D:
case Type::_1D:
case Type::BUFFER_1D:
return v.X(reg);
case SurfaceLoadStoreType::ARRAY_1D:
case Type::ARRAY_1D:
return v.ir.CompositeConstruct(v.X(reg), array(1));
case SurfaceLoadStoreType::_2D:
case Type::_2D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1));
case SurfaceLoadStoreType::ARRAY_2D:
case Type::ARRAY_2D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), array(2));
case SurfaceLoadStoreType::_3D:
case Type::_3D:
return v.ir.CompositeConstruct(v.X(reg), v.X(reg + 1), v.X(reg + 2));
}
throw NotImplementedException("Invalid type {}", type);
@@ -177,21 +174,21 @@ void TranslatorVisitor::SULD(u64 insn) {
BitField<51, 1, u64> is_bound;
BitField<52, 1, u64> d;
BitField<23, 1, u64> ba;
BitField<33, 3, SurfaceLoadStoreType> type;
BitField<24, 2, SURFLoadCache> cache;
BitField<20, 3, SurfaceLoadStoreSize> size; // .D
BitField<33, 3, Type> type;
BitField<24, 2, LoadCache> cache;
BitField<20, 3, Size> size; // .D
BitField<20, 4, u64> swizzle; // .P
BitField<49, 2, SurfaceLoadStoreClamp> clamp;
BitField<49, 2, Clamp> clamp;
BitField<0, 8, IR::Reg> dest_reg;
BitField<8, 8, IR::Reg> coord_reg;
BitField<36, 13, u64> bound_offset; // is_bound
BitField<39, 8, IR::Reg> bindless_reg; // !is_bound
} const suld{insn};
if (suld.clamp != SurfaceLoadStoreClamp::IGN) {
throw NotImplementedException("SurfaceLoadStoreClamp {}", suld.clamp.Value());
if (suld.clamp != Clamp::IGN) {
throw NotImplementedException("Clamp {}", suld.clamp.Value());
}
if (suld.cache != SURFLoadCache::CA && suld.cache != SURFLoadCache::CG) {
if (suld.cache != LoadCache::CA && suld.cache != LoadCache::CG) {
throw NotImplementedException("Cache {}", suld.cache.Value());
}
const bool is_typed{suld.d != 0};
@@ -237,21 +234,21 @@ void TranslatorVisitor::SUST(u64 insn) {
BitField<51, 1, u64> is_bound;
BitField<52, 1, u64> d;
BitField<23, 1, u64> ba;
BitField<33, 3, SurfaceLoadStoreType> type;
BitField<24, 2, SURFStoreCache> cache;
BitField<20, 3, SurfaceLoadStoreSize> size; // .D
BitField<33, 3, Type> type;
BitField<24, 2, StoreCache> cache;
BitField<20, 3, Size> size; // .D
BitField<20, 4, u64> swizzle; // .P
BitField<49, 2, SurfaceLoadStoreClamp> clamp;
BitField<49, 2, Clamp> clamp;
BitField<0, 8, IR::Reg> data_reg;
BitField<8, 8, IR::Reg> coord_reg;
BitField<36, 13, u64> bound_offset; // is_bound
BitField<39, 8, IR::Reg> bindless_reg; // !is_bound
} const sust{insn};
if (sust.clamp != SurfaceLoadStoreClamp::IGN) {
throw NotImplementedException("SurfaceLoadStoreClamp {}", sust.clamp.Value());
if (sust.clamp != Clamp::IGN) {
throw NotImplementedException("Clamp {}", sust.clamp.Value());
}
if (sust.cache != SURFStoreCache::WB && sust.cache != SURFStoreCache::CG) {
if (sust.cache != StoreCache::WB && sust.cache != StoreCache::CG) {
throw NotImplementedException("Cache {}", sust.cache.Value());
}
const bool is_typed{sust.d != 0};

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