Compare commits

..

8 Commits

Author SHA1 Message Date
lizzie 15e3acac93 fix span shit 2026-08-30 08:02:39 +02:00
lizzie 71d8796040 [audio_core] remove dangling Core::System& references
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2026-08-30 08:02:39 +02:00
Maufeat 28ab4a1a01 [kernel, service] Return ResultSessionClosed when a session is closed (#4318)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

I tried to run a homebrew game which tried to reply to a closed service. nnSdk expected ResultSessionClosed, we replied with ResultSuccess which mostly works but some have stricter handling and would terminate with abort.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4318
Reviewed-by: Lizzie and Samuel <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 08:00:18 +02:00
lizzie ccf3de02cf [dynarmic] optimise BlockOfCode to use less memory (#4303)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

removes unique_ptr indireciton with argCallback (lmao)
reorders jitState to be more cache friendly and yadda yadda
removes redundant BlockOfCode& ptr on constantPool
reorder blockOfCode to be btter
update dynarmic because it removes 3kb worth of useless data :)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4303
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-08-30 07:43:21 +02:00
PavelBARABANOV 1f03dee126 [fs] Add RenameDirectory support for same-parent directory renaming (#4312)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Fixes save corruption in Warhammer 40k: Mechanicus and other games
that rename directories within the same parent folder.

- Added RenameDirectory handler in IFileSystem (command 6)
- Implemented same-parent directory renaming using RenameDir

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4312
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-30 01:46:02 +02:00
xbzk 3df41c1e7a [android, ui] carousel: display-wise scaling, snapping fix, bottom insets rework (#4307)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
Another batch of improvements and fixes for Carousel.

- Added display wise scaling factor for compatibility with 16:9 and 4:3 devices;
- Fixed snap to center feature being lost sometimes;
- Reworked entire bottom inset mechanism (made it event driven, and added use of getInsetsIgnoringVisibility) to avoid weird resizing on Recents (alt+tab) transitions.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4307
Reviewed-by: Samuel <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
2026-08-29 22:04:18 +02:00
lizzie f4a8f9421a [common/net] fix linking errors due to C++11 ABI typedef mishandle (#4260)
Signed-off-by: lizzie <lizzie@eden-emu.dev>

- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------

basically bunch of linking errors due to gcc not liking
to compile HFA/whatever typedef stuffs
this is on non-x86_64 arch, ppc64

compiler where this occurs

```
gcc (Debian 14.2.0-19) 14.2.0
Copyright (C) 2024 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
```

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4260
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Maufeat <sahyno1996@gmail.com>
2026-08-29 20:59:57 +02:00
xbzk c0a85d0e53 [service, nvhost] added machinery to allow microsleep between nvdec read requests to avoid guest panic in some games (#4316)
- [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions).
- [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md)
- [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability.

-------------------
This one deserves a long story, but imma try to resume:

During investigating Absolum 1.2 black screen of death upon loading intro video, i've discovered guest was aborting for failing to allocate room for the video.

By logging everything prior to crash and decoding guest side instructions managed to confirm its media allocator was reading data faster than it was updating free available bucket list.

Since the IStorage::Read was happening 247 times before the crash, i've decided to add a very small sleep there, and boom, not only Absolum but some other titles got the same issue fixed.

But i was unsatisfied with the sleep and kept tracking guest instructions upstream in order to find a sync point for the read worker and the memory allocation update. But unfortunately the media allocator helpers live in guest, accessing memory directly via MMU, so any sync signaling would need to come from some dynarmic hack.

It's been 6 days now, so i've decided to polish the sleep: Moved it upstream to where i could have access for proper predicate, and added machinery to service and nvhost to support that. Now the sleep is restricted only for nvdec istorage reads. Any other reads will flow normally.

TL;DR: currently our code is so blazing async that guest is capable to request reads before its very self refresh it have freed room to do so. The sleep accepted as broadly stable was 600 us (MICROseconds), and it affects ONLY nvdec chunk reading.
Reports confirm that now videos are smoother now.

Code was polished at my knowledge limits.
Mostly machinery to track when a request comes from a process with nvdec active, and is istorage read.
I can provide more details if it comes to be needed.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4316
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Samuel <lizzie@eden-emu.dev>
2026-08-29 14:22:09 +02:00
184 changed files with 1898 additions and 1926 deletions
-20
View File
@@ -69,26 +69,6 @@ if (YUZU_STATIC_ROOM)
set(fmt_FORCE_BUNDLED ON) set(fmt_FORCE_BUNDLED ON)
endif() 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 # qt stuff
option(ENABLE_QT "Enable the Qt frontend" ON) option(ENABLE_QT "Enable the Qt frontend" ON)
option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF) option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)
+2 -2
View File
@@ -340,10 +340,10 @@
"version": "vulkan-sdk-%NUMERIC_VERSION%" "version": "vulkan-sdk-%NUMERIC_VERSION%"
}, },
"xbyak": { "xbyak": {
"hash": "b6475276b2faaeb315734ea8f4f8bd87ededcee768961b39679bee547e7f3e98884d8b7851e176d861dab30a80a76e6ea302f8c111483607dde969b4797ea95a", "hash": "e0aa0a603dd3ac1a39d82213df1e73c042831aec2d6b2fe382c899651eaae4ed7e8aeb6be9c41ea0097087c9d091961ab18f313cd6a9e10d621715ffd49bfe36",
"package": "xbyak", "package": "xbyak",
"repo": "herumi/xbyak", "repo": "herumi/xbyak",
"version": "v7.35.2" "version": "v7.40.1"
}, },
"zlib": { "zlib": {
"hash": "16fea4df307a68cf0035858abe2fd550250618a97590e202037acd18a666f57afc10f8836cbbd472d54a0e76539d0e558cb26f059d53de52ff90634bbf4f47d4", "hash": "16fea4df307a68cf0035858abe2fd550250618a97590e202037acd18a666f57afc10f8836cbbd472d54a0e76539d0e558cb26f059d53de52ff90634bbf4f47d4",
-1
View File
@@ -39,7 +39,6 @@ These options control dependencies.
- This option is subject for removal. - This option is subject for removal.
- `YUZU_TESTS` (ON) Compile tests - requires Catch2 - `YUZU_TESTS` (ON) Compile tests - requires Catch2
- `ENABLE_LTO` (OFF) Enable link-time optimization - `ENABLE_LTO` (OFF) Enable link-time optimization
- `ENABLE_UNITY_BUILD` (OFF) Enables "Unity/Jumbo" builds
- Not recommended on Windows - Not recommended on Windows
- UNIX may be better off appending `-flto=thin` to compiler args - UNIX may be better off appending `-flto=thin` to compiler args
- `USE_FASTER_LINKER` (OFF) Check if a faster linker is available - `USE_FASTER_LINKER` (OFF) Check if a faster linker is available
-5
View File
@@ -7,11 +7,6 @@
# Enable modules to include each other's files # Enable modules to include each other's files
include_directories(.) include_directories(.)
if (ENABLE_UNITY_BUILD)
set(CMAKE_UNITY_BUILD ON)
set(CMAKE_UNITY_BUILD_BATCH_SIZE ${UNITY_BATCH_SIZE})
endif()
# Dynarmic # Dynarmic
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM) if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
add_subdirectory(dynarmic) add_subdirectory(dynarmic)
@@ -47,7 +47,6 @@ import info.debatty.java.stringsimilarity.Jaccard
import info.debatty.java.stringsimilarity.JaroWinkler import info.debatty.java.stringsimilarity.JaroWinkler
import java.util.Locale import java.util.Locale
import androidx.core.content.edit import androidx.core.content.edit
import androidx.core.view.doOnNextLayout
class GamesFragment : Fragment() { class GamesFragment : Fragment() {
private var _binding: FragmentGamesBinding? = null private var _binding: FragmentGamesBinding? = null
@@ -59,7 +58,6 @@ class GamesFragment : Fragment() {
private var originalHeaderLeftMargin: Int? = null private var originalHeaderLeftMargin: Int? = null
private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID private var lastViewType: Int = GameAdapter.VIEW_TYPE_GRID
private var fallbackBottomInset: Int = 0
private var pendingPostReloadListSettle = false private var pendingPostReloadListSettle = false
private var pendingPostReloadListSettleGeneration = 0 private var pendingPostReloadListSettleGeneration = 0
private var gameListSubmitGeneration = 0 private var gameListSubmitGeneration = 0
@@ -227,12 +225,7 @@ class GamesFragment : Fragment() {
} }
else -> throw IllegalArgumentException("Invalid view type: $savedViewType") else -> throw IllegalArgumentException("Invalid view type: $savedViewType")
} }
if (savedViewType == GameAdapter.VIEW_TYPE_CAROUSEL) { if (savedViewType != GameAdapter.VIEW_TYPE_CAROUSEL) {
(binding.gridGames as? View)?.let { it -> ViewCompat.requestApplyInsets(it)}
doOnNextLayout { //Carousel: important to avoid overlap issues
(this as? CarouselRecyclerView)?.notifyLaidOut(fallbackBottomInset)
}
} else {
(this as? CarouselRecyclerView)?.setupCarousel(false) (this as? CarouselRecyclerView)?.setupCarousel(false)
} }
adapter = gameAdapter adapter = gameAdapter
@@ -590,11 +583,6 @@ class GamesFragment : Fragment() {
qlaunchButton.layoutParams = mlpQLaunch qlaunchButton.layoutParams = mlpQLaunch
} }
val navInsets = windowInsets.getInsets(WindowInsetsCompat.Type.navigationBars())
val gestureInsets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures())
val bottomInset = maxOf(navInsets.bottom, gestureInsets.bottom, cutoutInsets.bottom)
fallbackBottomInset = bottomInset
(binding.gridGames as? CarouselRecyclerView)?.notifyInsetsReady(bottomInset)
windowInsets windowInsets
} }
} }
@@ -12,13 +12,16 @@ import androidx.recyclerview.widget.PagerSnapHelper
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.cos import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin import kotlin.math.sin
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.adapters.GameAdapter import org.yuzu.yuzu_emu.adapters.GameAdapter
import androidx.core.view.doOnNextLayout import androidx.core.view.doOnNextLayout
import androidx.core.view.ViewCompat
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import androidx.preference.PreferenceManager import androidx.preference.PreferenceManager
import androidx.core.view.WindowInsetsCompat import androidx.core.view.WindowInsetsCompat
import org.yuzu.yuzu_emu.utils.FullscreenHelper
/** /**
* CarouselRecyclerView encapsulates all carousel content for the games UI. * CarouselRecyclerView encapsulates all carousel content for the games UI.
* It manages overlapping cards, center snapping, custom drawing order, * It manages overlapping cards, center snapping, custom drawing order,
@@ -32,7 +35,9 @@ class CarouselRecyclerView @JvmOverloads constructor(
private var overlapFactor: Float = 0f private var overlapFactor: Float = 0f
private var overlapPx: Int = 0 private var overlapPx: Int = 0
private var bottomInset: Int = -1 private var bottomInset: Int = 0
private var latestWindowInsets: WindowInsetsCompat? = null
private var cardGeometryInitialized: Boolean = false
private var overlapDecoration: OverlappingDecoration? = null private var overlapDecoration: OverlappingDecoration? = null
private var pagerSnapHelper: PagerSnapHelper? = null private var pagerSnapHelper: PagerSnapHelper? = null
private var scalingScrollListener: OnScrollListener? = null private var scalingScrollListener: OnScrollListener? = null
@@ -91,6 +96,38 @@ class CarouselRecyclerView @JvmOverloads constructor(
init { init {
setChildrenDrawingOrderEnabled(true) setChildrenDrawingOrderEnabled(true)
ViewCompat.setOnApplyWindowInsetsListener(this) { _, insets ->
latestWindowInsets = insets
updateCardGeometry()
applyCarouselPadding()
insets
}
}
override fun onAttachedToWindow() {
super.onAttachedToWindow()
ViewCompat.requestApplyInsets(this)
}
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
if (w != oldw || h != oldh) {
updateCardGeometry()
applyCarouselPadding()
}
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom)
if (isCarouselMode) updateChildScalesAndAlpha()
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
ViewCompat.requestApplyInsets(this)
post { updateCardGeometry() }
}
} }
override fun setAdapter(adapter: Adapter<*>?) { override fun setAdapter(adapter: Adapter<*>?) {
@@ -103,6 +140,8 @@ class CarouselRecyclerView @JvmOverloads constructor(
super.setAdapter(adapter) super.setAdapter(adapter)
(adapter as? GameAdapter)?.registerAdapterDataObserver(carouselAdapterObserver) (adapter as? GameAdapter)?.registerAdapterDataObserver(carouselAdapterObserver)
updateCardGeometry()
applyCarouselPadding()
} }
private fun calculateCenter(width: Int, paddingStart: Int, paddingEnd: Int): Int { private fun calculateCenter(width: Int, paddingStart: Int, paddingEnd: Int): Int {
@@ -253,40 +292,71 @@ class CarouselRecyclerView @JvmOverloads constructor(
} }
} }
fun notifyInsetsReady(newBottomInset: Int) { private fun resolveBottomInset(windowInsets: WindowInsetsCompat): Int {
if (bottomInset != newBottomInset) { val navigationBottom = if (FullscreenHelper.isFullscreenEnabled(context)) {
bottomInset = newBottomInset 0
}
if (isCarouselMode) {
setupCarousel(true)
} else { } else {
setupCarousel(false) windowInsets.getInsetsIgnoringVisibility(WindowInsetsCompat.Type.navigationBars()).bottom
} }
val gestureInsets = windowInsets.getInsetsIgnoringVisibility(
WindowInsetsCompat.Type.systemGestures()
)
val cutoutInsets = windowInsets.getInsetsIgnoringVisibility(
WindowInsetsCompat.Type.displayCutout()
)
return maxOf(navigationBottom, gestureInsets.bottom, cutoutInsets.bottom)
} }
fun notifyLaidOut(fallBackBottomInset: Int) { private fun updateCardGeometry() {
if (bottomInset < 0) bottomInset = fallBackBottomInset if (!isCarouselMode || height <= 0) return
var gameAdapter = adapter as? GameAdapter ?: return
var newCardSize = cardSize(bottomInset)
if (gameAdapter.cardSize != newCardSize) {
gameAdapter.setCardSize(newCardSize)
}
if (isCarouselMode) { val gameAdapter = adapter as? GameAdapter ?: return
setupCarousel(true) val windowInsets = latestWindowInsets ?: ViewCompat.getRootWindowInsets(this) ?: return
}
}
fun cardSize(bottomInset: Int): Int { if (cardGeometryInitialized && !hasWindowFocus()) return
val newBottomInset = resolveBottomInset(windowInsets).coerceIn(0, height)
val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1) val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1)
val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn( val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn(
0f, 0f,
1f 1f
) )
val scaledHeight = height * userFactor val screenWidth = resources.displayMetrics.widthPixels.toFloat()
val availableHeight = height - bottomInset val screenHeight = resources.displayMetrics.heightPixels.toFloat()
return minOf(scaledHeight.toInt(), availableHeight.toInt()) val aspectFactor = ((screenWidth / screenHeight) / (20f / 9f))
.pow(0.75f)
.coerceIn(0.5f, 1f)
val newCardSize = minOf(
(height * userFactor).toInt(),
height - newBottomInset,
(height * aspectFactor).toInt()
)
if (newCardSize <= 0) return
val insetChanged = bottomInset != newBottomInset
val cardSizeChanged = gameAdapter.cardSize != newCardSize
bottomInset = newBottomInset
cardGeometryInitialized = true
if (cardSizeChanged) gameAdapter.setCardSize(newCardSize)
if (insetChanged || cardSizeChanged) setupCarousel(true)
}
private fun applyCarouselPadding() {
if (!isCarouselMode) return
val gameAdapter = adapter as? GameAdapter ?: return
val cardSize = gameAdapter.cardSize
if (cardSize <= 0 || bottomInset < 0) return
val topPadding = ((height - bottomInset - cardSize) / 2).coerceAtLeast(0)
val sidePadding = (width - cardSize) / 2
if (paddingLeft != sidePadding || paddingTop != topPadding ||
paddingRight != sidePadding || paddingBottom != 0
) {
setPadding(sidePadding, topPadding, sidePadding, 0)
}
clipToPadding = false
} }
fun setupCarousel(enabled: Boolean) { fun setupCarousel(enabled: Boolean) {
@@ -315,9 +385,6 @@ class CarouselRecyclerView @JvmOverloads constructor(
internalFlingMultiplier internalFlingMultiplier
).coerceIn(1f, 5f) ).coerceIn(1f, 5f)
// Detach SnapHelper during setup
pagerSnapHelper?.attachToRecyclerView(null)
// Add overlap decoration if not present // Add overlap decoration if not present
if (overlapDecoration == null) { if (overlapDecoration == null) {
overlapDecoration = OverlappingDecoration(overlapPx) overlapDecoration = OverlappingDecoration(overlapPx)
@@ -335,12 +402,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
addOnScrollListener(scalingScrollListener!!) addOnScrollListener(scalingScrollListener!!)
} }
if (cardSize > 0) { applyCarouselPadding()
val topPadding = ((height - bottomInset - cardSize) / 2).coerceAtLeast(0) // Center vertically
val sidePadding = (width - cardSize) / 2 // Center first/last card
setPadding(sidePadding, topPadding, sidePadding, 0)
clipToPadding = false
}
if (pagerSnapHelper == null) { if (pagerSnapHelper == null) {
pagerSnapHelper = CenterPagerSnapHelper() pagerSnapHelper = CenterPagerSnapHelper()
@@ -362,6 +424,7 @@ class CarouselRecyclerView @JvmOverloads constructor(
} }
savedItemAnimator = null savedItemAnimator = null
} }
cardGeometryInitialized = false
useCustomDrawingOrder = false useCustomDrawingOrder = false
// Reset padding and fling // Reset padding and fling
setPadding(0, 0, 0, 0) setPadding(0, 0, 0, 0)
@@ -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-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,11 +5,17 @@
#include "common/assert.h" #include "common/assert.h"
namespace AudioCore::ADSP::OpusDecoder { namespace AudioCore::ADSP::OpusDecoder {
namespace {
bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
} // namespace
u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) { u32 OpusDecodeObject::GetWorkBufferSize(u32 channel_count) {
if (channel_count == 1 || channel_count == 2) if (!IsValidChannelCount(channel_count)) {
return 0; 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) { OpusDecodeObject& OpusDecodeObject::Initialize(u64 buffer, u64 buffer2) {
@@ -22,6 +22,10 @@ namespace AudioCore::ADSP::OpusDecoder {
namespace { namespace {
constexpr size_t OpusStreamCountMax = 255; constexpr size_t OpusStreamCountMax = 255;
bool IsValidChannelCount(u32 channel_count) {
return channel_count == 1 || channel_count == 2;
}
bool IsValidMultiStreamChannelCount(u32 channel_count) { bool IsValidMultiStreamChannelCount(u32 channel_count) {
return channel_count <= OpusStreamCountMax; return channel_count <= OpusStreamCountMax;
} }
+1 -1
View File
@@ -12,7 +12,7 @@
namespace AudioCore { namespace AudioCore {
AudioCore::AudioCore(Core::System& system) { AudioCore::AudioCore(Core::System& system) {
audio_manager.emplace(); audio_manager.emplace(system);
CreateSinks(); CreateSinks();
// Must be created after the sinks // Must be created after the sinks
adsp.emplace(system, *output_sink); adsp.emplace(system, *output_sink);
+12 -15
View File
@@ -15,12 +15,12 @@
namespace AudioCore::AudioIn { namespace AudioCore::AudioIn {
Manager::Manager(Core::System& system_) : system{system_} { Manager::Manager(Core::System& system) {
std::iota(session_ids.begin(), session_ids.end(), 0); std::iota(session_ids.begin(), session_ids.end(), 0);
num_free_sessions = MaxInSessions; num_free_sessions = MaxInSessions;
} }
Result Manager::AcquireSessionId(size_t& session_id) { Result Manager::AcquireSessionId(Core::System& system, size_t& session_id) {
if (num_free_sessions == 0) { if (num_free_sessions == 0) {
LOG_ERROR(Service_Audio, "All 4 AudioIn sessions are in use, cannot create any more"); LOG_ERROR(Service_Audio, "All 4 AudioIn sessions are in use, cannot create any more");
return Service::Audio::ResultOutOfSessions; return Service::Audio::ResultOutOfSessions;
@@ -31,7 +31,7 @@ Result Manager::AcquireSessionId(size_t& session_id) {
return ResultSuccess; return ResultSuccess;
} }
void Manager::ReleaseSessionId(const size_t session_id) { void Manager::ReleaseSessionId(Core::System& system, const size_t session_id) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LOG_DEBUG(Service_Audio, "Freeing AudioIn session {}", session_id); LOG_DEBUG(Service_Audio, "Freeing AudioIn session {}", session_id);
session_ids[free_session_id] = session_id; session_ids[free_session_id] = session_id;
@@ -41,21 +41,20 @@ void Manager::ReleaseSessionId(const size_t session_id) {
applet_resource_user_ids[session_id] = 0; applet_resource_user_ids[session_id] = 0;
} }
Result Manager::LinkToManager() { Result Manager::LinkToManager(Core::System& system) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
if (!linked_to_manager) { if (!linked_to_manager) {
system.AudioCore().GetAudioManager().SetInManager(std::bind(&Manager::BufferReleaseAndRegister, this)); system.AudioCore().GetAudioManager().SetInManager(&Manager::BufferReleaseAndRegister);
linked_to_manager = true; linked_to_manager = true;
} }
return ResultSuccess; return ResultSuccess;
} }
void Manager::Start() { void Manager::Start(Core::System& system) {
if (sessions_started) { if (sessions_started) {
return; return;
} }
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
for (auto& session : sessions) { for (auto& session : sessions) {
if (session) { if (session) {
@@ -66,21 +65,19 @@ void Manager::Start() {
sessions_started = true; sessions_started = true;
} }
void Manager::BufferReleaseAndRegister() { void Manager::BufferReleaseAndRegister(void *data, Core::System& system) noexcept {
std::scoped_lock l{mutex}; Manager* this_ = (Manager*)data;
for (auto& session : sessions) { std::scoped_lock l{this_->mutex};
for (auto& session : this_->sessions) {
if (session != nullptr) { if (session != nullptr) {
session->ReleaseAndRegisterBuffers(); session->ReleaseAndRegisterBuffers();
} }
} }
} }
u32 Manager::GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, u32 Manager::GetDeviceNames(Core::System& system, std::span<Renderer::AudioDevice::AudioDeviceName> names, [[maybe_unused]] const bool filter) {
[[maybe_unused]] const bool filter) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LinkToManager(system);
LinkToManager();
auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)}; auto input_devices{Sink::GetDeviceListForSink(Settings::values.sink_id.GetValue(), true)};
if (!input_devices.empty() && !names.empty()) { if (!input_devices.empty() && !names.empty()) {
names[0] = Renderer::AudioDevice::AudioDeviceName("Uac"); names[0] = Renderer::AudioDevice::AudioDeviceName("Uac");
+10 -11
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,31 +33,29 @@ public:
* @param session_id - Output session_id. * @param session_id - Output session_id.
* @return Result code. * @return Result code.
*/ */
Result AcquireSessionId(size_t& session_id); Result AcquireSessionId(Core::System& system, size_t& session_id);
/** /**
* Release a session id on close. * Release a session id on close.
* *
* @param session_id - Session id to free. * @param session_id - Session id to free.
*/ */
void ReleaseSessionId(size_t session_id); void ReleaseSessionId(Core::System& system, const size_t session_id);
/** /**
* Link the audio in manager to the main audio manager. * Link the audio in manager to the main audio manager.
* *
* @return Result code. * @return Result code.
*/ */
Result LinkToManager(); Result LinkToManager(Core::System& system);
/** /**
* Start the audio in manager. * Start the audio in manager.
*/ */
void Start(); void Start(Core::System& system);
/** /// @brief Callback function, called by the audio manager when the audio in event is signalled.
* Callback function, called by the audio manager when the audio in event is signalled. static void BufferReleaseAndRegister(void *data, Core::System& system) noexcept;
*/
void BufferReleaseAndRegister();
/** /**
* Get a list of audio in device names. * Get a list of audio in device names.
@@ -64,10 +65,8 @@ public:
* *
* @return Number of names written. * @return Number of names written.
*/ */
u32 GetDeviceNames(std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter); u32 GetDeviceNames(Core::System& system, std::span<Renderer::AudioDevice::AudioDeviceName> names, bool filter);
/// Core system
Core::System& system;
/// Array of session ids /// Array of session ids
std::array<size_t, MaxInSessions> session_ids{}; std::array<size_t, MaxInSessions> session_ids{};
/// Array of resource user ids /// Array of resource user ids
+3 -3
View File
@@ -11,8 +11,8 @@
namespace AudioCore { namespace AudioCore {
AudioManager::AudioManager() { AudioManager::AudioManager(Core::System& system) {
thread = std::jthread([this](std::stop_token stop_token) { thread = std::jthread([&](std::stop_token stop_token) {
Common::SetCurrentThreadName("AudioManager"); Common::SetCurrentThreadName("AudioManager");
std::unique_lock l{events.GetAudioEventLock()}; std::unique_lock l{events.GetAudioEventLock()};
events.ClearEvents(); events.ClearEvents();
@@ -25,7 +25,7 @@ AudioManager::AudioManager() {
const auto event_type = Event::Type(i); const auto event_type = Event::Type(i);
if (events.CheckAudioEventSet(event_type) || timed_out) { if (events.CheckAudioEventSet(event_type) || timed_out) {
if (buffer_events[i]) { if (buffer_events[i]) {
buffer_events[i](); buffer_events[i](this, system);
} }
} }
events.SetAudioEvent(event_type, false); events.SetAudioEvent(event_type, false);
+6 -3
View File
@@ -16,6 +16,10 @@
#include "audio_core/audio_event.h" #include "audio_core/audio_event.h"
namespace Core {
class System;
}
union Result; union Result;
namespace AudioCore { namespace AudioCore {
@@ -34,10 +38,9 @@ namespace AudioCore {
* This is only used by audio in and audio out. * This is only used by audio in and audio out.
*/ */
class AudioManager { class AudioManager {
using BufferEventFunc = std::function<void()>; using BufferEventFunc = void (*)(void *data, Core::System& system) noexcept;
public: public:
explicit AudioManager(); explicit AudioManager(Core::System& system);
/** /**
* Shutdown the audio manager. * Shutdown the audio manager.
+10 -15
View File
@@ -14,12 +14,12 @@
namespace AudioCore::AudioOut { namespace AudioCore::AudioOut {
Manager::Manager(Core::System& system_) : system{system_} { Manager::Manager(Core::System& system) {
std::iota(session_ids.begin(), session_ids.end(), 0); std::iota(session_ids.begin(), session_ids.end(), 0);
num_free_sessions = MaxOutSessions; num_free_sessions = MaxOutSessions;
} }
Result Manager::AcquireSessionId(size_t& session_id) { Result Manager::AcquireSessionId(Core::System& system, size_t& session_id) {
if (num_free_sessions == 0) { if (num_free_sessions == 0) {
LOG_ERROR(Service_Audio, "All 12 Audio Out sessions are in use, cannot create any more"); LOG_ERROR(Service_Audio, "All 12 Audio Out sessions are in use, cannot create any more");
return Service::Audio::ResultOutOfSessions; return Service::Audio::ResultOutOfSessions;
@@ -30,7 +30,7 @@ Result Manager::AcquireSessionId(size_t& session_id) {
return ResultSuccess; return ResultSuccess;
} }
void Manager::ReleaseSessionId(const size_t session_id) { void Manager::ReleaseSessionId(Core::System& system, const size_t session_id) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
LOG_DEBUG(Service_Audio, "Freeing AudioOut session {}", session_id); LOG_DEBUG(Service_Audio, "Freeing AudioOut session {}", session_id);
session_ids[free_session_id] = session_id; session_ids[free_session_id] = session_id;
@@ -40,17 +40,17 @@ void Manager::ReleaseSessionId(const size_t session_id) {
applet_resource_user_ids[session_id] = 0; applet_resource_user_ids[session_id] = 0;
} }
Result Manager::LinkToManager() { Result Manager::LinkToManager(Core::System& system) {
std::scoped_lock l{mutex}; std::scoped_lock l{mutex};
if (!linked_to_manager) { if (!linked_to_manager) {
system.AudioCore().GetAudioManager().SetOutManager(std::bind(&Manager::BufferReleaseAndRegister, this)); system.AudioCore().GetAudioManager().SetOutManager(&Manager::BufferReleaseAndRegister);
linked_to_manager = true; linked_to_manager = true;
} }
return ResultSuccess; return ResultSuccess;
} }
void Manager::Start() { void Manager::Start(Core::System& system) {
if (sessions_started) { if (sessions_started) {
return; return;
} }
@@ -65,19 +65,14 @@ void Manager::Start() {
sessions_started = true; sessions_started = true;
} }
void Manager::BufferReleaseAndRegister() { void Manager::BufferReleaseAndRegister(void *data, Core::System& system) noexcept {
std::scoped_lock l{mutex}; Manager* this_ = (Manager*)data;
for (auto& session : sessions) { std::scoped_lock l{this_->mutex};
for (auto& session : this_->sessions) {
if (session != nullptr) { if (session != nullptr) {
session->ReleaseAndRegisterBuffers(); session->ReleaseAndRegisterBuffers();
} }
} }
} }
u32 Manager::GetAudioOutDeviceNames(
std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const {
names.emplace_back("DeviceOut");
return 1;
}
} // namespace AudioCore::AudioOut } // namespace AudioCore::AudioOut
+8 -15
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -29,42 +32,32 @@ public:
* @param session_id - Output session_id. * @param session_id - Output session_id.
* @return Result code. * @return Result code.
*/ */
Result AcquireSessionId(size_t& session_id); Result AcquireSessionId(Core::System& system, size_t& session_id);
/** /**
* Release a session id on close. * Release a session id on close.
* *
* @param session_id - Session id to free. * @param session_id - Session id to free.
*/ */
void ReleaseSessionId(size_t session_id); void ReleaseSessionId(Core::System& system, const size_t session_id);
/** /**
* Link this manager to the main audio manager. * Link this manager to the main audio manager.
* *
* @return Result code. * @return Result code.
*/ */
Result LinkToManager(); Result LinkToManager(Core::System& system);
/** /**
* Start the audio out manager. * Start the audio out manager.
*/ */
void Start(); void Start(Core::System& system);
/** /**
* Callback function, called by the audio manager when the audio out event is signalled. * Callback function, called by the audio manager when the audio out event is signalled.
*/ */
void BufferReleaseAndRegister(); static void BufferReleaseAndRegister(void* data, Core::System& system) noexcept;
/**
* Get a list of audio out device names.
*
* @param names - Output container to write names to.
* @return Number of names written.
*/
u32 GetAudioOutDeviceNames(std::vector<Renderer::AudioDevice::AudioDeviceName>& names) const;
/// Core system
Core::System& system;
/// Array of session ids /// Array of session ids
std::array<size_t, MaxOutSessions> session_ids{}; std::array<size_t, MaxOutSessions> session_ids{};
/// Array of resource user ids /// Array of resource user ids
+8 -3
View File
@@ -1,15 +1,20 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "audio_core/audio_render_manager.h" #include "audio_core/audio_render_manager.h"
#include "audio_core/common/audio_renderer_parameter.h" #include "audio_core/common/audio_renderer_parameter.h"
#include "audio_core/renderer/system_manager.h"
#include "audio_core/common/feature_support.h" #include "audio_core/common/feature_support.h"
#include "core/core.h" #include "core/core.h"
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
Manager::Manager(Core::System& system_) Manager::Manager(Core::System& system_)
: system{system_}, system_manager{std::make_unique<SystemManager>(system)} { : system_manager{std::make_unique<SystemManager>(system_)}
{
std::iota(session_ids.begin(), session_ids.end(), 0); std::iota(session_ids.begin(), session_ids.end(), 0);
} }
@@ -59,11 +64,11 @@ u32 Manager::GetSessionCount() const {
return session_count; return session_count;
} }
bool Manager::AddSystem(System& system_) { bool Manager::AddSystem(Renderer::System& system_) {
return system_manager->Add(system_); return system_manager->Add(system_);
} }
bool Manager::RemoveSystem(System& system_) { bool Manager::RemoveSystem(Renderer::System& system_) {
return system_manager->Remove(system_); return system_manager->Remove(system_);
} }
+5 -4
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -71,7 +74,7 @@ public:
* @param system - The system to add. * @param system - The system to add.
* @return True if the system was successfully added, otherwise false. * @return True if the system was successfully added, otherwise false.
*/ */
bool AddSystem(System& system); bool AddSystem(Renderer::System& system);
/** /**
* Remove a renderer system from the manager. * Remove a renderer system from the manager.
@@ -79,7 +82,7 @@ public:
* @param system - The system to remove. * @param system - The system to remove.
* @return True if the system was successfully removed, otherwise false. * @return True if the system was successfully removed, otherwise false.
*/ */
bool RemoveSystem(System& system); bool RemoveSystem(Renderer::System& system);
/** /**
* Free a session id when the system wants to shut down. * Free a session id when the system wants to shut down.
@@ -89,8 +92,6 @@ public:
void ReleaseSessionId(s32 session_id); void ReleaseSessionId(s32 session_id);
private: private:
/// Core system
Core::System& system;
/// Session ids, -1 when in use /// Session ids, -1 when in use
std::array<s32, MaxRendererSessions> session_ids{}; std::array<s32, MaxRendererSessions> session_ids{};
/// Number of active renderers /// Number of active renderers
+18 -22
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -16,8 +19,9 @@ namespace AudioCore {
*/ */
class WorkbufferAllocator { class WorkbufferAllocator {
public: public:
explicit WorkbufferAllocator(std::span<u8> buffer_, u64 size_) explicit WorkbufferAllocator(std::span<u8> buffer_)
: buffer{reinterpret_cast<u64>(buffer_.data())}, size{size_} {} : buffer{buffer_}
{}
/** /**
* Allocate the given count of T elements, aligned to alignment. * Allocate the given count of T elements, aligned to alignment.
@@ -29,36 +33,31 @@ public:
template <typename T> template <typename T>
std::span<T> Allocate(u64 count, u64 alignment) { std::span<T> Allocate(u64 count, u64 alignment) {
u64 out{0}; u64 out{0};
u64 byte_size{count * sizeof(T)}; u64 byte_size = count * sizeof(T);
if (byte_size > 0) { if (byte_size > 0) {
auto current{buffer + offset}; auto current{uintptr_t(buffer.data()) + offset};
auto aligned_buffer{Common::AlignUp(current, alignment)}; auto aligned_buffer{Common::AlignUp(current, alignment)};
if (aligned_buffer + byte_size <= buffer + size) { if (aligned_buffer + byte_size <= uintptr_t(buffer.data()) + buffer.size()) {
out = aligned_buffer; out = aligned_buffer;
offset = byte_size - buffer + aligned_buffer; offset = byte_size - uintptr_t(buffer.data()) + aligned_buffer;
} else { } else {
LOG_ERROR( LOG_ERROR(
Service_Audio, Service_Audio,
"Allocated buffer was too small to hold new alloc.\nAllocator size={:08X}, " "Allocated buffer was too small to hold new alloc.\nAllocator size={:08X}, "
"offset={:08X}.\nAttempting to allocate {:08X} with alignment={:02X}", "offset={:08X}.\nAttempting to allocate {:08X} with alignment={:02X}",
size, offset, byte_size, alignment); buffer.size(), offset, byte_size, alignment);
count = 0; count = 0;
} }
} }
return std::span<T>(reinterpret_cast<T*>(out), count); return std::span<T>(reinterpret_cast<T*>(out), count);
} }
/** /// @brief Align the current offset to the given alignment.
* Align the current offset to the given alignment. /// @param alignment - The required starting alignment.
*
* @param alignment - The required starting alignment.
*/
void Align(u64 alignment) { void Align(u64 alignment) {
auto current{buffer + offset}; auto current{uintptr_t(buffer.data()) + offset};
auto aligned_buffer{Common::AlignUp(current, alignment)}; auto aligned_buffer{Common::AlignUp(current, alignment)};
offset = 0 - buffer + aligned_buffer; offset = 0 - uintptr_t(buffer.data()) + aligned_buffer;
} }
/** /**
@@ -76,7 +75,7 @@ public:
* @return The size of the current buffer. * @return The size of the current buffer.
*/ */
u64 GetSize() const { u64 GetSize() const {
return size; return buffer.size();
} }
/** /**
@@ -85,14 +84,11 @@ public:
* @return The remaining size left in the buffer. * @return The remaining size left in the buffer.
*/ */
u64 GetRemainingSize() const { u64 GetRemainingSize() const {
return size - offset; return buffer.size() - offset;
} }
private: private:
/// The buffer into which we are allocating. const std::span<u8> buffer;
u64 buffer;
/// Size of the buffer we're allocating to.
u64 size;
/// Current offset into the buffer, an error will be thrown if it exceeds size. /// Current offset into the buffer, an error will be thrown if it exceeds size.
u64 offset{}; u64 offset{};
}; };
+21 -20
View File
@@ -11,42 +11,43 @@
namespace AudioCore::AudioIn { namespace AudioCore::AudioIn {
In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_) In::In(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event, : manager{manager_}, parent_mutex{manager.mutex}, event{event_}
session_id_} {} , audio_system{system_, event, session_id_}
{}
void In::Free() { void In::Free(Core::System& system) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
manager.ReleaseSessionId(system.GetSessionId()); manager.ReleaseSessionId(system, audio_system.GetSessionId());
} }
System& In::GetSystem() { System& In::GetSystem() {
return system; return audio_system;
} }
AudioIn::State In::GetState() { AudioIn::State In::GetState() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetState(); return audio_system.GetState();
} }
Result In::StartSystem() { Result In::StartSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Start(); return audio_system.Start();
} }
void In::StartSession() { void In::StartSession() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.StartSession(); audio_system.StartSession();
} }
Result In::StopSystem() { Result In::StopSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Stop(); return audio_system.Stop();
} }
Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) { Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.AppendBuffer(buffer, tag)) { if (audio_system.AppendBuffer(buffer, tag)) {
return ResultSuccess; return ResultSuccess;
} }
return Service::Audio::ResultBufferCountReached; return Service::Audio::ResultBufferCountReached;
@@ -54,20 +55,20 @@ Result In::AppendBuffer(const AudioInBuffer& buffer, u64 tag) {
void In::ReleaseAndRegisterBuffers() { void In::ReleaseAndRegisterBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.GetState() == State::Started) { if (audio_system.GetState() == State::Started) {
system.ReleaseBuffers(); audio_system.ReleaseBuffers();
system.RegisterBuffers(); audio_system.RegisterBuffers();
} }
} }
bool In::FlushAudioInBuffers() { bool In::FlushAudioInBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.FlushAudioInBuffers(); return audio_system.FlushAudioInBuffers();
} }
u32 In::GetReleasedBuffers(std::span<u64> tags) { u32 In::GetReleasedBuffers(std::span<u64> tags) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetReleasedBuffers(tags); return audio_system.GetReleasedBuffers(tags);
} }
Kernel::KReadableEvent& In::GetBufferEvent() { Kernel::KReadableEvent& In::GetBufferEvent() {
@@ -77,27 +78,27 @@ Kernel::KReadableEvent& In::GetBufferEvent() {
f32 In::GetVolume() const { f32 In::GetVolume() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetVolume(); return audio_system.GetVolume();
} }
void In::SetVolume(f32 volume) { void In::SetVolume(f32 volume) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.SetVolume(volume); audio_system.SetVolume(volume);
} }
bool In::ContainsAudioBuffer(u64 tag) const { bool In::ContainsAudioBuffer(u64 tag) const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag); return audio_system.ContainsAudioBuffer(tag);
} }
u32 In::GetBufferCount() const { u32 In::GetBufferCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetBufferCount(); return audio_system.GetBufferCount();
} }
u64 In::GetPlayedSampleCount() const { u64 In::GetPlayedSampleCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount(); return audio_system.GetPlayedSampleCount();
} }
} // namespace AudioCore::AudioIn } // namespace AudioCore::AudioIn
+5 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,7 +33,7 @@ public:
/** /**
* Free this audio in from the audio in manager. * Free this audio in from the audio in manager.
*/ */
void Free(); void Free(Core::System& system);
/** /**
* Get this audio in's system. * Get this audio in's system.
@@ -141,7 +144,7 @@ private:
/// Buffer event, signalled when buffers are ready to be released /// Buffer event, signalled when buffers are ready to be released
Kernel::KEvent* event; Kernel::KEvent* event;
/// Main audio in system /// Main audio in system
System system; System audio_system;
}; };
} // namespace AudioCore::AudioIn } // namespace AudioCore::AudioIn
+4 -4
View File
@@ -14,16 +14,14 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event.h"
namespace AudioCore::AudioIn {
// See texture_cache/util.h // See texture_cache/util.h
template<typename T, size_t N> template<typename T, size_t N>
#if BOOST_VERSION >= 108100 || __GNUC__ > 12 #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; return v;
} }
#else #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; std::vector<T> u;
for (auto const& e : v) for (auto const& e : v)
u.push_back(e); u.push_back(e);
@@ -31,6 +29,8 @@ template<typename T, size_t N>
} }
#endif #endif
namespace AudioCore::AudioIn {
System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_) System::System(Core::System& system_, Kernel::KEvent* event_, const size_t session_id_)
: system{system_}, buffer_event{event_}, : system{system_}, buffer_event{event_},
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {} session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
+24 -20
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,42 +11,43 @@
namespace AudioCore::AudioOut { namespace AudioCore::AudioOut {
Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_) Out::Out(Core::System& system_, Manager& manager_, Kernel::KEvent* event_, size_t session_id_)
: manager{manager_}, parent_mutex{manager.mutex}, event{event_}, system{system_, event, : manager{manager_}, parent_mutex{manager.mutex}, event{event_}
session_id_} {} , audio_system{system_, event, session_id_}
{}
void Out::Free() { void Out::Free(Core::System& system) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
manager.ReleaseSessionId(system.GetSessionId()); manager.ReleaseSessionId(system, audio_system.GetSessionId());
} }
System& Out::GetSystem() { System& Out::GetSystem() {
return system; return audio_system;
} }
AudioOut::State Out::GetState() { AudioOut::State Out::GetState() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetState(); return audio_system.GetState();
} }
Result Out::StartSystem() { Result Out::StartSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Start(); return audio_system.Start();
} }
void Out::StartSession() { void Out::StartSession() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.StartSession(); audio_system.StartSession();
} }
Result Out::StopSystem() { Result Out::StopSystem() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.Stop(); return audio_system.Stop();
} }
Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) { Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.AppendBuffer(buffer, tag)) { if (audio_system.AppendBuffer(buffer, tag)) {
return ResultSuccess; return ResultSuccess;
} }
return Service::Audio::ResultBufferCountReached; return Service::Audio::ResultBufferCountReached;
@@ -51,20 +55,20 @@ Result Out::AppendBuffer(const AudioOutBuffer& buffer, const u64 tag) {
void Out::ReleaseAndRegisterBuffers() { void Out::ReleaseAndRegisterBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
if (system.GetState() == State::Started) { if (audio_system.GetState() == State::Started) {
system.ReleaseBuffers(); audio_system.ReleaseBuffers();
system.RegisterBuffers(); audio_system.RegisterBuffers();
} }
} }
bool Out::FlushAudioOutBuffers() { bool Out::FlushAudioOutBuffers() {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.FlushAudioOutBuffers(); return audio_system.FlushAudioOutBuffers();
} }
u32 Out::GetReleasedBuffers(std::span<u64> tags) { u32 Out::GetReleasedBuffers(std::span<u64> tags) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetReleasedBuffers(tags); return audio_system.GetReleasedBuffers(tags);
} }
Kernel::KReadableEvent& Out::GetBufferEvent() { Kernel::KReadableEvent& Out::GetBufferEvent() {
@@ -74,27 +78,27 @@ Kernel::KReadableEvent& Out::GetBufferEvent() {
f32 Out::GetVolume() const { f32 Out::GetVolume() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetVolume(); return audio_system.GetVolume();
} }
void Out::SetVolume(const f32 volume) { void Out::SetVolume(const f32 volume) {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
system.SetVolume(volume); audio_system.SetVolume(volume);
} }
bool Out::ContainsAudioBuffer(const u64 tag) const { bool Out::ContainsAudioBuffer(const u64 tag) const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.ContainsAudioBuffer(tag); return audio_system.ContainsAudioBuffer(tag);
} }
u32 Out::GetBufferCount() const { u32 Out::GetBufferCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetBufferCount(); return audio_system.GetBufferCount();
} }
u64 Out::GetPlayedSampleCount() const { u64 Out::GetPlayedSampleCount() const {
std::scoped_lock l{parent_mutex}; std::scoped_lock l{parent_mutex};
return system.GetPlayedSampleCount(); return audio_system.GetPlayedSampleCount();
} }
} // namespace AudioCore::AudioOut } // namespace AudioCore::AudioOut
+5 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -30,7 +33,7 @@ public:
/** /**
* Free this audio out from the audio out manager. * Free this audio out from the audio out manager.
*/ */
void Free(); void Free(Core::System& system);
/** /**
* Get this audio out's system. * Get this audio out's system.
@@ -141,7 +144,7 @@ private:
/// Buffer event, signalled when buffers are ready to be released /// Buffer event, signalled when buffers are ready to be released
Kernel::KEvent* event; Kernel::KEvent* event;
/// Main audio out system /// Main audio out system
System system; System audio_system;
}; };
} // namespace AudioCore::AudioOut } // namespace AudioCore::AudioOut
+4 -3
View File
@@ -14,15 +14,14 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/hle/kernel/k_event.h" #include "core/hle/kernel/k_event.h"
namespace AudioCore::AudioOut {
// See texture_cache/util.h // See texture_cache/util.h
template<typename T, size_t N> template<typename T, size_t N>
#if BOOST_VERSION >= 108100 || __GNUC__ > 12 #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; return v;
} }
#else #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; std::vector<T> u;
for (auto const& e : v) for (auto const& e : v)
u.push_back(e); u.push_back(e);
@@ -30,6 +29,8 @@ template<typename T, size_t N>
} }
#endif #endif
namespace AudioCore::AudioOut {
System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_) System::System(Core::System& system_, Kernel::KEvent* event_, size_t session_id_)
: system{system_}, buffer_event{event_}, : system{system_}, buffer_event{event_},
session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {} session_id{session_id_}, session{std::make_unique<DeviceSession>(system_)} {}
+18 -23
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,56 +16,48 @@
namespace AudioCore::Renderer { namespace AudioCore::Renderer {
Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* rendered_event) Renderer::Renderer(Core::System& system_, Manager& manager_, Kernel::KEvent* rendered_event)
: core{system_}, manager{manager_}, system{system_, rendered_event} {} : system{system_}, manager{manager_}
, audio_system{system_, rendered_event}
{}
Result Renderer::Initialize(const AudioRendererParameterInternal& params, Result Renderer::Initialize(const AudioRendererParameterInternal& params, Kernel::KTransferMemory* transfer_memory, const u64 transfer_memory_size, Kernel::KProcess* process_handle, const u64 applet_resource_user_id, const s32 session_id) {
Kernel::KTransferMemory* transfer_memory,
const u64 transfer_memory_size, Kernel::KProcess* process_handle,
const u64 applet_resource_user_id, const s32 session_id) {
if (params.execution_mode == ExecutionMode::Auto) { if (params.execution_mode == ExecutionMode::Auto) {
if (!manager.AddSystem(system)) { if (!manager.AddSystem(audio_system)) {
LOG_ERROR(Service_Audio, LOG_ERROR(Service_Audio, "Both Audio Render sessions are in use, cannot create any more");
"Both Audio Render sessions are in use, cannot create any more");
return Service::Audio::ResultOutOfSessions; return Service::Audio::ResultOutOfSessions;
} }
system_registered = true; system_registered = true;
} }
initialized = true; initialized = true;
system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, audio_system.Initialize(params, transfer_memory, transfer_memory_size, process_handle, applet_resource_user_id, session_id);
applet_resource_user_id, session_id);
return ResultSuccess; return ResultSuccess;
} }
void Renderer::Finalize() { void Renderer::Finalize() {
auto session_id{system.GetSessionId()}; auto const session_id{audio_system.GetSessionId()};
audio_system.Finalize();
system.Finalize();
if (system_registered) { if (system_registered) {
manager.RemoveSystem(system); manager.RemoveSystem(audio_system);
system_registered = false; system_registered = false;
} }
manager.ReleaseSessionId(session_id); manager.ReleaseSessionId(session_id);
} }
System& Renderer::GetSystem() { System& Renderer::GetSystem() {
return system; return audio_system;
} }
void Renderer::Start() { void Renderer::Start() {
system.Start(); audio_system.Start();
} }
void Renderer::Stop() { void Renderer::Stop() {
system.Stop(); audio_system.Stop();
} }
Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performance, Result Renderer::RequestUpdate(std::span<const u8> input, std::span<u8> performance, std::span<u8> output) {
std::span<u8> output) { return audio_system.Update(input, performance, output);
return system.Update(input, performance, output);
} }
} // namespace AudioCore::Renderer } // namespace AudioCore::Renderer
+5 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -84,7 +87,7 @@ public:
private: private:
/// System core /// System core
Core::System& core; Core::System& system;
/// Manager this renderer is registered with /// Manager this renderer is registered with
Manager& manager; Manager& manager;
/// Is the audio renderer initialized? /// Is the audio renderer initialized?
@@ -92,7 +95,7 @@ private:
/// Is the system registered with the manager? /// Is the system registered with the manager?
bool system_registered{}; bool system_registered{};
/// Audio render system, main driver of audio rendering /// Audio render system, main driver of audio rendering
System system; System audio_system;
}; };
} // namespace Renderer } // namespace Renderer
@@ -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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
@@ -16,7 +16,7 @@ namespace AudioCore::Renderer {
* @param memory - Core memory for writing. * @param memory - Core memory for writing.
* @param aux_info - Memory address pointing to the AuxInfo to reset. * @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) { if (aux_info == 0) {
LOG_ERROR(Service_Audio, "Aux info is 0!"); LOG_ERROR(Service_Audio, "Aux info is 0!");
return; return;
@@ -134,7 +134,7 @@ void CaptureCommand::Process(const AudioRenderer::CommandListProcessor& processo
WriteAuxBufferDsp(*processor.memory, send_buffer_info, send_buffer, count_max, input_buffer, WriteAuxBufferDsp(*processor.memory, send_buffer_info, send_buffer, count_max, input_buffer,
processor.sample_count, write_offset, update_count); processor.sample_count, write_offset, update_count);
} else { } else {
CaptureResetAuxBufferDsp(*processor.memory, send_buffer_info); ResetAuxBufferDsp(*processor.memory, send_buffer_info);
} }
} }
+1 -1
View File
@@ -145,7 +145,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
PoolMapper pool_mapper(process_handle, false); PoolMapper pool_mapper(process_handle, false);
pool_mapper.InitializeSystemPool(memory_pool_info, workbuffer.get(), workbuffer_size); pool_mapper.InitializeSystemPool(memory_pool_info, workbuffer.get(), workbuffer_size);
WorkbufferAllocator allocator({workbuffer.get(), workbuffer_size}, workbuffer_size); WorkbufferAllocator allocator({workbuffer.get(), workbuffer_size});
samples_workbuffer = samples_workbuffer =
allocator.Allocate<s32>((voice_channels + mix_buffer_count) * sample_count, 0x10); allocator.Allocate<s32>((voice_channels + mix_buffer_count) * sample_count, 0x10);
+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-FileCopyrightText: 2011 Google, Inc.
// SPDX-FileContributor: Geoff Pike // SPDX-FileContributor: Geoff Pike
// SPDX-FileContributor: Jyrki Alakuijala // SPDX-FileContributor: Jyrki Alakuijala
@@ -30,6 +27,8 @@
#define WORDS_BIGENDIAN 1 #define WORDS_BIGENDIAN 1
#endif #endif
using namespace std;
namespace Common { namespace Common {
static u64 unaligned_load64(const char* p) { 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. // Return a 16-byte hash for 48 bytes. Quick and dirty.
// Callers do best to use "random-looking" values for a and b. // 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; a += w;
b = Rotate(b + a + z, 21); b = Rotate(b + a + z, 21);
u64 c = a; u64 c = a;
a += x; a += x;
a += y; a += y;
b += Rotate(a, 44); 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. // 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, return WeakHashLen32WithSeeds(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a,
b); b);
} }
@@ -190,8 +189,8 @@ u64 CityHash64(const char* s, size_t len) {
u64 x = Fetch64(s + len - 40); u64 x = Fetch64(s + len - 40);
u64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); u64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56);
u64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); u64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24));
std::pair<u64, u64> v = WeakHashLen32WithSeeds(s + len - 64, len, z); 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> w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x);
x = x * k1 + Fetch64(s); x = x * k1 + Fetch64(s);
// Decrease len to the nearest multiple of 64, and operate on 64-byte chunks. // 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: // We expect len >= 128 to be the common case. Keep 56 bytes of state:
// v, w, x, y, and z. // v, w, x, y, and z.
std::pair<u64, u64> v, w; pair<u64, u64> v, w;
u64 x = seed[0]; u64 x = seed[0];
u64 y = seed[1]; u64 y = seed[1];
u64 z = len * k1; u64 z = len * k1;
-2
View File
@@ -16,5 +16,3 @@
#ifdef __GNUC__ #ifdef __GNUC__
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
#endif #endif
#undef INVALID_SOCKET
+4 -4
View File
@@ -11,14 +11,14 @@
namespace Common::Net { namespace Common::Net {
typedef struct { struct Asset {
std::string name; std::string name;
std::string url; std::string url;
std::string path; std::string path;
std::string filename; std::string filename;
} Asset; };
typedef struct Release { struct Release {
std::string title; std::string title;
std::string body; std::string body;
std::string tag; std::string tag;
@@ -39,7 +39,7 @@ typedef struct Release {
static std::optional<Release> FromJson(const std::string_view& json, const std::string &host, const std::string& repo); static std::optional<Release> FromJson(const std::string_view& json, const std::string &host, const std::string& repo);
static std::vector<Release> ListFromJson(const nlohmann::json &json, const std::string &host, const std::string &repo); static std::vector<Release> ListFromJson(const nlohmann::json &json, const std::string &host, const std::string &repo);
static std::vector<Release> ListFromJson(const std::string_view &json, const std::string &host, const std::string &repo); static std::vector<Release> ListFromJson(const std::string_view &json, const std::string &host, const std::string &repo);
} Release; };
// Make a request via httplib, and return the response body if applicable. // Make a request via httplib, and return the response body if applicable.
std::optional<std::string> MakeRequest(const std::string &url, const std::string &path); std::optional<std::string> MakeRequest(const std::string &url, const std::string &path);
+8 -7
View File
@@ -7,18 +7,19 @@
#pragma once #pragma once
#include <dynarmic/interface/halt_reason.h> #include <dynarmic/interface/halt_reason.h>
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
namespace Core { namespace Core {
inline constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step; constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step;
inline constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort; constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort;
inline constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2; constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2;
inline constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3; constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3;
inline constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4; constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4;
inline constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6; 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::StepThread) == u64(StepThread));
static_assert(u64(HaltReason::DataAbort) == u64(DataAbort)); static_assert(u64(HaltReason::DataAbort) == u64(DataAbort));
static_assert(u64(HaltReason::BreakLoop) == u64(BreakLoop)); static_assert(u64(HaltReason::BreakLoop) == u64(BreakLoop));
+34 -6
View File
@@ -4,6 +4,7 @@
#include <array> #include <array>
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <unordered_map>
#include <utility> #include <utility>
#include "game_settings.h" #include "game_settings.h"
@@ -248,12 +249,30 @@ struct System::Impl {
} }
} }
void SetNVDECActive(bool is_nvdec_active) { void NotifyNVDECChannelOpen(u64 process_id) {
nvdec_active = is_nvdec_active; std::scoped_lock lock{nvdec_active_mutex};
++nvdec_active_channels[process_id];
}
void NotifyNVDECChannelClose(u64 process_id) {
std::scoped_lock lock{nvdec_active_mutex};
const auto it = nvdec_active_channels.find(process_id);
if (it == nvdec_active_channels.end()) {
return;
}
if (--it->second == 0) {
nvdec_active_channels.erase(it);
}
} }
bool GetNVDECActive() { bool GetNVDECActive() {
return nvdec_active; std::scoped_lock lock{nvdec_active_mutex};
return !nvdec_active_channels.empty();
}
bool IsNVDECActiveForProcess(u64 process_id) {
std::scoped_lock lock{nvdec_active_mutex};
return nvdec_active_channels.contains(process_id);
} }
void InitializeDebugger(System& system, u16 port) { void InitializeDebugger(System& system, u16 port) {
@@ -505,6 +524,8 @@ struct System::Impl {
mutable std::mutex suspend_guard; mutable std::mutex suspend_guard;
std::mutex general_channel_mutex; std::mutex general_channel_mutex;
std::mutex nvdec_active_mutex;
std::unordered_map<u64, u32> nvdec_active_channels;
std::atomic_bool is_paused{}; std::atomic_bool is_paused{};
std::atomic_bool is_shutting_down{}; std::atomic_bool is_shutting_down{};
std::atomic_bool is_powered_on{}; std::atomic_bool is_powered_on{};
@@ -512,7 +533,6 @@ struct System::Impl {
bool extended_memory_layout : 1 = false; bool extended_memory_layout : 1 = false;
bool exit_locked : 1 = false; bool exit_locked : 1 = false;
bool exit_requested : 1 = false; bool exit_requested : 1 = false;
bool nvdec_active : 1 = false;
void EnsureGeneralChannelInitialized(System& system) { void EnsureGeneralChannelInitialized(System& system) {
if (!general_channel_event) { if (!general_channel_event) {
@@ -576,14 +596,22 @@ void System::UnstallApplication() {
impl->UnstallApplication(); impl->UnstallApplication();
} }
void System::SetNVDECActive(bool is_nvdec_active) { void System::NotifyNVDECChannelOpen(u64 process_id) {
impl->SetNVDECActive(is_nvdec_active); impl->NotifyNVDECChannelOpen(process_id);
}
void System::NotifyNVDECChannelClose(u64 process_id) {
impl->NotifyNVDECChannelClose(process_id);
} }
bool System::GetNVDECActive() { bool System::GetNVDECActive() {
return impl->GetNVDECActive(); return impl->GetNVDECActive();
} }
bool System::IsNVDECActiveForProcess(u64 process_id) {
return impl->IsNVDECActiveForProcess(process_id);
}
void System::InitializeDebugger() { void System::InitializeDebugger() {
impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue()); impl->InitializeDebugger(*this, Settings::values.gdbstub_port.GetValue());
} }
+3 -1
View File
@@ -191,8 +191,10 @@ public:
std::unique_lock<std::mutex> StallApplication(); std::unique_lock<std::mutex> StallApplication();
void UnstallApplication(); void UnstallApplication();
void SetNVDECActive(bool is_nvdec_active); void NotifyNVDECChannelOpen(u64 process_id);
void NotifyNVDECChannelClose(u64 process_id);
[[nodiscard]] bool GetNVDECActive(); [[nodiscard]] bool GetNVDECActive();
[[nodiscard]] bool IsNVDECActiveForProcess(u64 process_id);
/** /**
* Initialize the debugger. * Initialize the debugger.
-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) { std::shared_ptr<EventType> CreateEvent(std::string name, TimedCallback&& callback) {
return std::make_shared<EventType>(std::move(callback), std::move(name)); 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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // 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>, static_assert(std::is_trivially_copyable_v<SaveDataFilter>,
"Data type must be trivially copyable."); "Data type must be trivially copyable.");
struct SaveDataHashSalt { struct HashSalt {
static constexpr size_t Size = 32; static constexpr size_t Size = 32;
std::array<u8, Size> value; std::array<u8, Size> value;
}; };
static_assert(std::is_trivially_copyable_v<SaveDataHashSalt>, "Data type must be trivially copyable."); static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
static_assert(sizeof(SaveDataHashSalt) == SaveDataHashSalt::Size); static_assert(sizeof(HashSalt) == HashSalt::Size);
struct SaveDataCreationInfo2 { struct SaveDataCreationInfo2 {
@@ -210,7 +210,7 @@ struct SaveDataCreationInfo2 {
u8 reserved1; u8 reserved1;
bool is_hash_salt_enabled; bool is_hash_salt_enabled;
u8 reserved2; u8 reserved2;
SaveDataHashSalt hash_salt; HashSalt hash_salt;
SaveDataMetaType meta_type; SaveDataMetaType meta_type;
u8 reserved3; u8 reserved3;
s32 meta_size; 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-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // 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.h"
#include "core/file_sys/vfs/vfs_vector.h" #include "core/file_sys/vfs/vfs_vector.h"
namespace FileSys::RomFSBuilder { namespace FileSys {
constexpr u64 FS_MAX_PATH = 0x301; 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-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,7 +9,7 @@
#include "common/common_types.h" #include "common/common_types.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
namespace FileSys::RomFSBuilder { namespace FileSys {
struct RomFSBuildDirectoryContext; struct RomFSBuildDirectoryContext;
struct RomFSBuildFileContext; 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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -38,7 +38,7 @@ struct RomFSHeader {
}; };
static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size."); static_assert(sizeof(RomFSHeader) == 0x50, "RomFSHeader has incorrect size.");
struct RomFSDirectoryEntry { struct DirectoryEntry {
u32_le parent; u32_le parent;
u32_le sibling; u32_le sibling;
u32_le child_dir; u32_le child_dir;
@@ -46,9 +46,9 @@ struct RomFSDirectoryEntry {
u32_le hash; u32_le hash;
u32_le name_length; 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 parent;
u32_le sibling; u32_le sibling;
u64_le offset; u64_le offset;
@@ -56,7 +56,7 @@ struct RomFSFileEntry {
u32_le hash; u32_le hash;
u32_le name_length; u32_le name_length;
}; };
static_assert(sizeof(RomFSFileEntry) == 0x20, "RomFSFileEntry has incorrect size."); static_assert(sizeof(FileEntry) == 0x20, "FileEntry has incorrect size.");
struct RomFSTraversalContext { struct RomFSTraversalContext {
RomFSHeader header; RomFSHeader header;
@@ -84,14 +84,14 @@ std::pair<EntryType, std::string> GetEntry(const RomFSTraversalContext& ctx, siz
return {entry, std::move(name)}; 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) { 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) { 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, void ProcessFile(const RomFSTraversalContext& ctx, u32 this_file_offset,
@@ -163,7 +163,7 @@ VirtualFile CreateRomFS(VirtualDir dir, VirtualDir ext) {
if (dir == nullptr) if (dir == nullptr)
return nullptr; return nullptr;
RomFSBuilder::RomFSBuildContext ctx{dir, ext}; RomFSBuildContext ctx{dir, ext};
return ConcatenatedVfsFile::MakeConcatenatedFile(0, dir->GetName(), ctx.Build()); 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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -10,12 +10,6 @@
#include "common/fs/path_util.h" #include "common/fs/path_util.h"
#include "core/file_sys/vfs/vfs.h" #include "core/file_sys/vfs/vfs.h"
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
#undef CopyFile
#undef MoveFile
namespace FileSys { namespace FileSys {
VfsFilesystem::VfsFilesystem(VirtualDir root_) : root(std::move(root_)) {} 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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -99,10 +99,6 @@ private:
std::string name; std::string name;
}; };
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
// An implementation of VfsDirectory that maintains two vectors for subdirectories and files. // An implementation of VfsDirectory that maintains two vectors for subdirectories and files.
// Vector data is supplied upon construction. // Vector data is supplied upon construction.
class VectorVfsDirectory : public VfsDirectory { class VectorVfsDirectory : public VfsDirectory {
+2 -2
View File
@@ -1216,7 +1216,7 @@ Result KServerSession::ReceiveRequest(KernelCore& kernel, uintptr_t server_messa
} }
Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size,
KPhysicalAddress server_message_paddr, bool is_hle) { KPhysicalAddress server_message_paddr, bool is_hle, bool session_closed) {
// Lock the session. // Lock the session.
KScopedLightLock lk{m_lock}; KScopedLightLock lk{m_lock};
@@ -1248,7 +1248,7 @@ Result KServerSession::SendReply(KernelCore& kernel, uintptr_t server_message, u
KEvent* event = request->GetEvent(); KEvent* event = request->GetEvent();
// Check whether we're closed. // Check whether we're closed.
const bool closed = (client_thread == nullptr || m_parent->IsClientClosed()); const bool closed = (client_thread == nullptr || m_parent->IsClientClosed() || session_closed);
Result result = ResultSuccess; Result result = ResultSuccess;
if (!closed) { if (!closed) {
+3 -3
View File
@@ -54,14 +54,14 @@ public:
Result OnRequest(KernelCore& kernel, KSessionRequest* request); Result OnRequest(KernelCore& kernel, KSessionRequest* request);
Result SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, Result SendReply(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size,
KPhysicalAddress server_message_paddr, bool is_hle = false); KPhysicalAddress server_message_paddr, bool is_hle = false, bool session_closed = false);
Result ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size, Result ReceiveRequest(KernelCore& kernel, uintptr_t server_message, uintptr_t server_buffer_size,
KPhysicalAddress server_message_paddr, KPhysicalAddress server_message_paddr,
std::shared_ptr<Service::HLERequestContext>* out_context = nullptr, std::shared_ptr<Service::HLERequestContext>* out_context = nullptr,
std::weak_ptr<Service::SessionRequestManager> manager = {}); std::weak_ptr<Service::SessionRequestManager> manager = {});
Result SendReplyHLE(KernelCore& kernel) { Result SendReplyHLE(KernelCore& kernel, bool session_closed = false) {
R_RETURN(this->SendReply(kernel, 0, 0, 0, true)); R_RETURN(this->SendReply(kernel, 0, 0, 0, true, session_closed));
} }
Result ReceiveRequestHLE(KernelCore& kernel, std::shared_ptr<Service::HLERequestContext>* out_context, Result ReceiveRequestHLE(KernelCore& kernel, std::shared_ptr<Service::HLERequestContext>* out_context,
+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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-late // SPDX-License-Identifier: GPL-2.0-or-late
@@ -13,10 +13,6 @@
#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h" #include "core/hle/kernel/svc.h"
#undef OutputDebugString
#undef GetObject
#undef CreateProcess
namespace Kernel::Svc { namespace Kernel::Svc {
static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) { static uint32_t GetArg32(std::span<uint64_t, 8> args, int n) {
+10 -10
View File
@@ -11,11 +11,7 @@
namespace Kernel::Svc { namespace Kernel::Svc {
namespace { namespace {
[[nodiscard]] inline constexpr bool IsValidSetAddressRange(u64 address, u64 size) { constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
return address + size > address;
}
[[nodiscard]] inline constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
switch (perm) { switch (perm) {
case MemoryPermission::None: case MemoryPermission::None:
case MemoryPermission::Read: 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 // Helper function that performs the common sanity checks for svcMapMemory
// and svcUnmapMemory. This is doable, as both functions perform their sanitizing // and svcUnmapMemory. This is doable, as both functions perform their sanitizing
// in the same order. // in the same order.
@@ -50,17 +53,14 @@ Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr
R_THROW(ResultInvalidSize); R_THROW(ResultInvalidSize);
} }
// Checks if address + size is greater than the given address if (!IsValidAddressRange(dst_addr, size)) {
// 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)) {
LOG_ERROR(Kernel_SVC, LOG_ERROR(Kernel_SVC,
"Destination is not a valid address range, addr={:#016x}, size={:#016x}", "Destination is not a valid address range, addr={:#016x}, size={:#016x}",
dst_addr, size); dst_addr, size);
R_THROW(ResultInvalidCurrentMemory); 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}", LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr={:#016x}, size={:#016x}",
src_addr, size); src_addr, size);
R_THROW(ResultInvalidCurrentMemory); R_THROW(ResultInvalidCurrentMemory);
@@ -11,11 +11,11 @@
namespace Kernel::Svc { namespace Kernel::Svc {
namespace { namespace {
[[nodiscard]] inline constexpr bool IsValidAddressRange(u64 address, u64 size) { constexpr bool IsValidAddressRange(u64 address, u64 size) {
return address + size > address; return address + size > address;
} }
[[nodiscard]] inline constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) { constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
switch (perm) { switch (perm) {
case Svc::MemoryPermission::None: case Svc::MemoryPermission::None:
case Svc::MemoryPermission::Read: case Svc::MemoryPermission::Read:
+7 -6
View File
@@ -9,12 +9,13 @@
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioIn::IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager, size_t session_id, IAudioIn::IAudioIn(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioCore::AudioIn::AudioInParameter& in_params, const std::string& device_name, const AudioInParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id) Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioIn"}, process{handle}, service_context{system_, "IAudioIn"}, : 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, manager, event,
session_id)} { session_id)} {
// clang-format off // clang-format off
@@ -49,7 +50,7 @@ IAudioIn::IAudioIn(Core::System& system_, AudioCore::AudioIn::Manager& manager,
} }
IAudioIn::~IAudioIn() { IAudioIn::~IAudioIn() {
impl->Free(); impl->Free(system);
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close(system.Kernel()); process->Close(system.Kernel());
} }
@@ -70,12 +71,12 @@ Result IAudioIn::Stop() {
R_RETURN(impl->StopSystem()); 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) { u64 buffer_client_ptr) {
R_RETURN(this->AppendAudioInBufferAuto(buffer, 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) { u64 buffer_client_ptr) {
if (buffer.empty()) { if (buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!"); LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioInBuffer!");
+11 -10
View File
@@ -10,6 +10,7 @@
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioIn;
IAudioInManager::IAudioInManager(Core::System& system_) IAudioInManager::IAudioInManager(Core::System& system_)
: ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>( : ServiceFramework{system_, "audin:u"}, impl{std::make_unique<AudioCore::AudioIn::Manager>(
@@ -36,11 +37,11 @@ Result IAudioInManager::ListAudioIns(
R_RETURN(this->ListAudioInsAutoFiltered(out_audio_ins, out_count)); 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, Out<SharedPointer<IAudioIn>> out_audio_in,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name, OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name, InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioIn::AudioInParameter parameter, AudioInParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) { ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
@@ -55,9 +56,9 @@ Result IAudioInManager::ListAudioInsAuto(
} }
Result IAudioInManager::OpenAudioInAuto( 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, 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) { InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name, R_RETURN(this->OpenAudioInProtocolSpecified(out_parameter_internal, out_audio_in, out_name,
@@ -67,15 +68,15 @@ Result IAudioInManager::OpenAudioInAuto(
Result IAudioInManager::ListAudioInsAutoFiltered( Result IAudioInManager::ListAudioInsAutoFiltered(
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) { OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_audio_ins, Out<u32> out_count) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
*out_count = impl->GetDeviceNames(out_audio_ins, true); *out_count = impl->GetDeviceNames(system, out_audio_ins, true);
R_SUCCEED(); R_SUCCEED();
} }
Result IAudioInManager::OpenAudioInProtocolSpecified( 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, OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name,
InArray<AudioDeviceName, BufferAttr_HipcAutoSelect> name, Protocol protocol, 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) { ClientAppletResourceUserId aruid) {
LOG_DEBUG(Service_Audio, "called"); LOG_DEBUG(Service_Audio, "called");
@@ -92,8 +93,8 @@ Result IAudioInManager::OpenAudioInProtocolSpecified(
size_t new_session_id{}; size_t new_session_id{};
R_TRY(impl->LinkToManager()); R_TRY(impl->LinkToManager(system));
R_TRY(impl->AcquireSessionId(new_session_id)); R_TRY(impl->AcquireSessionId(system, new_session_id));
LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioIn, session_id={}, free sessions={}", new_session_id,
impl->num_free_sessions); impl->num_free_sessions);
@@ -106,7 +107,7 @@ Result IAudioInManager::OpenAudioInProtocolSpecified(
auto& out_system = impl->sessions[new_session_id]->GetSystem(); auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal = *out_parameter_internal =
AudioCore::AudioIn::AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(), AudioInParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(), .channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()), .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())}; .state = static_cast<u32>(out_system.GetState())};
+6 -5
View File
@@ -13,9 +13,10 @@
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOut::IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manager, size_t session_id, IAudioOut::IAudioOut(Core::System& system_, Manager& manager, size_t session_id,
const std::string& device_name, const AudioCore::AudioOut::AudioOutParameter& in_params, const std::string& device_name, const AudioOutParameter& in_params,
Kernel::KProcess* handle, u64 applet_resource_user_id) Kernel::KProcess* handle, u64 applet_resource_user_id)
: ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"}, : ServiceFramework{system_, "IAudioOut"}, service_context{system_, "IAudioOut"},
event{service_context.CreateEvent("AudioOutEvent")}, process{handle}, event{service_context.CreateEvent("AudioOutEvent")}, process{handle},
@@ -45,7 +46,7 @@ IAudioOut::IAudioOut(Core::System& system_, AudioCore::AudioOut::Manager& manage
} }
IAudioOut::~IAudioOut() { IAudioOut::~IAudioOut() {
impl->Free(); impl->Free(system);
service_context.CloseEvent(event); service_context.CloseEvent(event);
process->Close(system.Kernel()); process->Close(system.Kernel());
} }
@@ -67,12 +68,12 @@ Result IAudioOut::Stop() {
} }
Result IAudioOut::AppendAudioOutBuffer( 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)); R_RETURN(this->AppendAudioOutBufferAuto(audio_out_buffer, buffer_client_ptr));
} }
Result IAudioOut::AppendAudioOutBufferAuto( 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()) { if (audio_out_buffer.empty()) {
LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!"); LOG_ERROR(Service_Audio, "Input buffer is too small for an AudioOutBuffer!");
R_THROW(Audio::ResultInsufficientBuffer); R_THROW(Audio::ResultInsufficientBuffer);
@@ -11,6 +11,7 @@
#include "core/memory.h" #include "core/memory.h"
namespace Service::Audio { namespace Service::Audio {
using namespace AudioCore::AudioOut;
IAudioOutManager::IAudioOutManager(Core::System& system_) IAudioOutManager::IAudioOutManager(Core::System& system_)
: ServiceFramework{system_, "audout:u"} : ServiceFramework{system_, "audout:u"}
@@ -35,11 +36,11 @@ Result IAudioOutManager::ListAudioOuts(
R_RETURN(this->ListAudioOutsAuto(out_audio_outs, out_count)); 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, Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name, OutArray<AudioDeviceName, BufferAttr_HipcMapAlias> out_name,
InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name, InArray<AudioDeviceName, BufferAttr_HipcMapAlias> name,
AudioCore::AudioOut::AudioOutParameter parameter, AudioOutParameter parameter,
InCopyHandle<Kernel::KProcess> process_handle, InCopyHandle<Kernel::KProcess> process_handle,
ClientAppletResourceUserId aruid) { ClientAppletResourceUserId aruid) {
R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name, R_RETURN(this->OpenAudioOutAuto(out_parameter_internal, out_audio_out, out_name, name,
@@ -61,10 +62,10 @@ Result IAudioOutManager::ListAudioOutsAuto(
} }
Result IAudioOutManager::OpenAudioOutAuto( Result IAudioOutManager::OpenAudioOutAuto(
Out<AudioCore::AudioOut::AudioOutParameterInternal> out_parameter_internal, Out<AudioOutParameterInternal> out_parameter_internal,
Out<SharedPointer<IAudioOut>> out_audio_out, Out<SharedPointer<IAudioOut>> out_audio_out,
OutArray<AudioDeviceName, BufferAttr_HipcAutoSelect> out_name, 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) { InCopyHandle<Kernel::KProcess> process_handle, ClientAppletResourceUserId aruid) {
if (!process_handle) { if (!process_handle) {
LOG_ERROR(Service_Audio, "Failed to get process handle"); LOG_ERROR(Service_Audio, "Failed to get process handle");
@@ -76,8 +77,8 @@ Result IAudioOutManager::OpenAudioOutAuto(
} }
size_t new_session_id{}; size_t new_session_id{};
R_TRY(impl->LinkToManager()); R_TRY(impl->LinkToManager(system));
R_TRY(impl->AcquireSessionId(new_session_id)); R_TRY(impl->AcquireSessionId(system, new_session_id));
const auto device_name = Common::StringFromBuffer(name[0].name); const auto device_name = Common::StringFromBuffer(name[0].name);
LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id, LOG_DEBUG(Service_Audio, "Opening new AudioOut, sessionid={}, free sessions={}", new_session_id,
@@ -94,7 +95,7 @@ Result IAudioOutManager::OpenAudioOutAuto(
auto& out_system = impl->sessions[new_session_id]->GetSystem(); auto& out_system = impl->sessions[new_session_id]->GetSystem();
*out_parameter_internal = *out_parameter_internal =
AudioCore::AudioOut::AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(), AudioOutParameterInternal{.sample_rate = out_system.GetSampleRate(),
.channel_count = out_system.GetChannelCount(), .channel_count = out_system.GetChannelCount(),
.sample_format = static_cast<u32>(out_system.GetSampleFormat()), .sample_format = static_cast<u32>(out_system.GetSampleFormat()),
.state = static_cast<u32>(out_system.GetState())}; .state = static_cast<u32>(out_system.GetState())};
@@ -4,20 +4,21 @@
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // 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/audio/audio_renderer.h"
#include "core/hle/service/cmif_serialization.h" #include "core/hle/service/cmif_serialization.h"
namespace Service::Audio { 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, AudioCore::AudioRendererParameterInternal& params,
Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size, Kernel::KTransferMemory* transfer_memory, u64 transfer_memory_size,
Kernel::KProcess* process_handle_, u64 applet_resource_user_id, Kernel::KProcess* process_handle_, u64 applet_resource_user_id,
s32 session_id) s32 session_id)
: ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"}, : ServiceFramework{system_, "IAudioRenderer"}, service_context{system_, "IAudioRenderer"},
rendered_event{service_context.CreateEvent("IAudioRendererEvent")}, manager{manager_}, 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 // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"}, {0, D<&IAudioRenderer::GetSampleRate>, "GetSampleRate"},
@@ -14,13 +14,16 @@
#include <cstring> #include <cstring>
namespace Service::News { 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 std::string_view sv{buf.data(), buf.size()};
const auto nul = sv.find('\0'); const auto nul = sv.find('\0');
return nul == std::string_view::npos ? sv : sv.substr(0, nul); return nul == std::string_view::npos ? sv : sv.substr(0, nul);
} }
} // namespace
INewsDataService::INewsDataService(Core::System& system_) INewsDataService::INewsDataService(Core::System& system_)
: ServiceFramework{system_, "INewsDataService"} { : ServiceFramework{system_, "INewsDataService"} {
static const FunctionInfo functions[] = { 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(); const auto list = NewsStorage::Instance().ListAll();
if (!list.empty()) { 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); opened_payload = std::move(found->payload);
return true; return true;
} }
@@ -64,7 +67,7 @@ bool INewsDataService::TryOpen(std::string_view key, std::string_view user) {
Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) { Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) {
EnsureBuiltinNewsLoaded(); 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, {})) { if (TryOpen(key, {})) {
R_SUCCEED(); R_SUCCEED();
@@ -76,8 +79,8 @@ Result INewsDataService::Open(InBuffer<BufferAttr_HipcMapAlias> name) {
Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) { Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) {
EnsureBuiltinNewsLoaded(); EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS(record.news_id); const auto key = ToStringView(record.news_id);
const auto user = ToStringViewNDS(record.user_id); const auto user = ToStringView(record.user_id);
if (TryOpen(key, user)) { if (TryOpen(key, user)) {
R_SUCCEED(); R_SUCCEED();
@@ -89,8 +92,8 @@ Result INewsDataService::OpenWithNewsRecordV1(NewsRecordV1 record) {
Result INewsDataService::OpenWithNewsRecord(NewsRecord record) { Result INewsDataService::OpenWithNewsRecord(NewsRecord record) {
EnsureBuiltinNewsLoaded(); EnsureBuiltinNewsLoaded();
const auto key = ToStringViewNDS(record.news_id); const auto key = ToStringView(record.news_id);
const auto user = ToStringViewNDS(record.user_id); const auto user = ToStringView(record.user_id);
if (TryOpen(key, user)) { if (TryOpen(key, user)) {
R_SUCCEED(); 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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
@@ -15,13 +15,13 @@
namespace Service::News { namespace Service::News {
namespace { 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 {}; if (buf.empty()) return {};
auto data = reinterpret_cast<const char*>(buf.data()); auto data = reinterpret_cast<const char*>(buf.data());
return {data, strnlen(data, buf.size())}; 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 {}; if (buf.empty()) return {};
return {buf.data(), strnlen(buf.data(), buf.size())}; 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-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
@@ -9,8 +6,6 @@
namespace Service::News { namespace Service::News {
#undef CreateEvent
IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_) IOverwriteEventHolder::IOverwriteEventHolder(Core::System& system_)
: ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_, : ServiceFramework{system_, "IOverwriteEventHolder"}, service_context{system_,
"IOverwriteEventHolder"} { "IOverwriteEventHolder"} {
@@ -18,8 +18,6 @@
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
#include "core/hle/service/sm/sm.h" #include "core/hle/service/sm/sm.h"
#undef GetCurrentTime
namespace Service::Capture { namespace Service::Capture {
AlbumManager::AlbumManager(Core::System& system_) : system{system_} {} AlbumManager::AlbumManager(Core::System& system_) : system{system_} {}
-2
View File
@@ -19,8 +19,6 @@
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/reporter.h" #include "core/reporter.h"
#undef far
namespace Service::Fatal { namespace Service::Fatal {
Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_, Module::Interface::Interface(std::shared_ptr<Module> module_, Core::System& system_,
@@ -32,10 +32,6 @@
#include "core/hle/service/server_manager.h" #include "core/hle/service/server_manager.h"
#include "core/loader/loader.h" #include "core/loader/loader.h"
#undef CreateFile
#undef DeleteFile
#undef CreateDirectory
namespace Service::FileSystem { namespace Service::FileSystem {
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base, static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
@@ -231,12 +227,13 @@ Result VfsDirectoryServiceWrapper::RenameDirectory(const std::string& src_path_,
std::string src_path(Common::FS::SanitizePath(src_path_)); std::string src_path(Common::FS::SanitizePath(src_path_));
std::string dest_path(Common::FS::SanitizePath(dest_path_)); std::string dest_path(Common::FS::SanitizePath(dest_path_));
auto src = GetDirectoryRelativeWrapped(backing, src_path); auto src = GetDirectoryRelativeWrapped(backing, src_path);
if (src == nullptr)
return FileSys::ResultPathNotFound;
if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) { if (Common::FS::GetParentPath(src_path) == Common::FS::GetParentPath(dest_path)) {
// Use more-optimized vfs implementation rename. std::string full_src_path = backing->GetFullPath() + "/" + src_path;
if (src == nullptr) std::string full_dest_path = backing->GetFullPath() + "/" + dest_path;
return FileSys::ResultPathNotFound; if (!Common::FS::RenameDir(full_src_path, full_dest_path)) {
if (!src->Rename(Common::FS::GetFilename(dest_path))) {
// TODO(DarkLordZach): Find a better error code for this
return ResultUnknown; return ResultUnknown;
} }
return ResultSuccess; return ResultSuccess;
@@ -24,7 +24,7 @@ IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir dir_, SizeGe
{3, D<&IFileSystem::DeleteDirectory>, "DeleteDirectory"}, {3, D<&IFileSystem::DeleteDirectory>, "DeleteDirectory"},
{4, D<&IFileSystem::DeleteDirectoryRecursively>, "DeleteDirectoryRecursively"}, {4, D<&IFileSystem::DeleteDirectoryRecursively>, "DeleteDirectoryRecursively"},
{5, D<&IFileSystem::RenameFile>, "RenameFile"}, {5, D<&IFileSystem::RenameFile>, "RenameFile"},
{6, nullptr, "RenameDirectory"}, {6, D<&IFileSystem::RenameDirectory>, "RenameDirectory"},
{7, D<&IFileSystem::GetEntryType>, "GetEntryType"}, {7, D<&IFileSystem::GetEntryType>, "GetEntryType"},
{8, D<&IFileSystem::OpenFile>, "OpenFile"}, {8, D<&IFileSystem::OpenFile>, "OpenFile"},
{9, D<&IFileSystem::OpenDirectory>, "OpenDirectory"}, {9, D<&IFileSystem::OpenDirectory>, "OpenDirectory"},
@@ -88,6 +88,14 @@ Result IFileSystem::RenameFile(
R_RETURN(backend->RenameFile(FileSys::Path(old_path->str), FileSys::Path(new_path->str))); R_RETURN(backend->RenameFile(FileSys::Path(old_path->str), FileSys::Path(new_path->str)));
} }
Result IFileSystem::RenameDirectory(
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> old_path,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> new_path) {
LOG_DEBUG(Service_FS, "called. directory '{}' to directory '{}'", old_path->str, new_path->str);
R_RETURN(backend->RenameDirectory(FileSys::Path(old_path->str), FileSys::Path(new_path->str)));
}
Result IFileSystem::OpenFile(OutInterface<IFile> out_interface, Result IFileSystem::OpenFile(OutInterface<IFile> out_interface,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path, const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path,
u32 mode) { u32 mode) {
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -36,6 +39,8 @@ public:
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path); const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path);
Result RenameFile(const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> old_path, Result RenameFile(const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> old_path,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> new_path); const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> new_path);
Result RenameDirectory(const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> old_path,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> new_path);
Result OpenFile(OutInterface<IFile> out_interface, Result OpenFile(OutInterface<IFile> out_interface,
const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path, u32 mode); const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path, u32 mode);
Result OpenDirectory(OutInterface<IDirectory> out_interface, Result OpenDirectory(OutInterface<IDirectory> out_interface,
-2
View File
@@ -27,8 +27,6 @@
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/memory.h" #include "core/memory.h"
#undef SendMessage
namespace Service { namespace Service {
SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_) SessionRequestHandler::SessionRequestHandler(Kernel::KernelCore& kernel_, const char* service_name_)
+1 -2
View File
@@ -212,9 +212,8 @@ struct NifmNetworkProfileData {
NifmWirelessSettingData wireless_setting_data{}; NifmWirelessSettingData wireless_setting_data{};
IpSettingData ip_setting_data{}; IpSettingData ip_setting_data{};
}; };
static_assert(sizeof(NifmNetworkProfileData) == 0x18E,
"NifmNetworkProfileData has incorrect size.");
#pragma pack(pop) #pragma pack(pop)
static_assert(sizeof(NifmNetworkProfileData) == 0x18E, "NifmNetworkProfileData has incorrect size.");
struct PendingProfile { struct PendingProfile {
std::array<char, 0x21> ssid{}; std::array<char, 0x21> ssid{};
@@ -8,6 +8,7 @@
#include "common/assert.h" #include "common/assert.h"
#include "common/logging.h" #include "common/logging.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/service/nvdrv/core/container.h" #include "core/hle/service/nvdrv/core/container.h"
#include "core/hle/service/nvdrv/devices/ioctl_serialization.h" #include "core/hle/service/nvdrv/devices/ioctl_serialization.h"
#include "core/hle/service/nvdrv/devices/nvhost_nvdec.h" #include "core/hle/service/nvdrv/devices/nvhost_nvdec.h"
@@ -71,17 +72,23 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
void nvhost_nvdec::OnOpen(NvCore::SessionId session_id, DeviceFD fd) { void nvhost_nvdec::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
LOG_INFO(Service_NVDRV, "NVDEC video stream started"); LOG_INFO(Service_NVDRV, "NVDEC video stream started");
system.SetNVDECActive(true);
sessions[fd] = session_id; sessions[fd] = session_id;
if (const auto* session = core.GetSession(session_id);
session != nullptr && session->process != nullptr) {
system.NotifyNVDECChannelOpen(session->process->GetId());
}
host1x.StartDevice(fd, Tegra::Host1x::ChannelType::NvDec, channel_syncpoint); host1x.StartDevice(fd, Tegra::Host1x::ChannelType::NvDec, channel_syncpoint);
} }
void nvhost_nvdec::OnClose(DeviceFD fd) { void nvhost_nvdec::OnClose(DeviceFD fd) {
LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
host1x.StopDevice(fd, Tegra::Host1x::ChannelType::NvDec); host1x.StopDevice(fd, Tegra::Host1x::ChannelType::NvDec);
system.SetNVDECActive(false);
auto it = sessions.find(fd); auto it = sessions.find(fd);
if (it != sessions.end()) { if (it != sessions.end()) {
if (const auto* session = core.GetSession(it->second);
session != nullptr && session->process != nullptr) {
system.NotifyNVDECChannelClose(session->process->GetId());
}
sessions.erase(it); sessions.erase(it);
} }
} }
@@ -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-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -13,8 +10,6 @@
namespace Service::PSC::Time { namespace Service::PSC::Time {
class ContextWriter; class ContextWriter;
#undef GetCurrentTime
class SystemClockCore { class SystemClockCore {
public: public:
explicit SystemClockCore(SteadyClockCore& steady_clock) : m_steady_clock{steady_clock} {} explicit SystemClockCore(SteadyClockCore& steady_clock) : m_steady_clock{steady_clock} {}
@@ -19,8 +19,6 @@ class System;
namespace Service::PSC::Time { namespace Service::PSC::Time {
#undef GetCurrentTime
class SystemClock final : public ServiceFramework<SystemClock> { class SystemClock final : public ServiceFramework<SystemClock> {
public: public:
explicit SystemClock(Core::System& system, SystemClockCore& system_clock_core, bool can_write_clock, bool can_write_uninitialized_clock); explicit SystemClock(Core::System& system, SystemClockCore& system_clock_core, bool can_write_clock, bool can_write_uninitialized_clock);
+1 -1
View File
@@ -393,7 +393,7 @@ Result ServerManager::CompleteSyncRequest(Session* session) {
} }
// Send the reply. // Send the reply.
res = server_session->SendReplyHLE(m_system.Kernel()); res = server_session->SendReplyHLE(m_system.Kernel(), service_res == IPC::ResultSessionClosed);
// If the session has been closed, we're done. // If the session has been closed, we're done.
if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) { if (res == Kernel::ResultSessionClosed || service_res == IPC::ResultSessionClosed) {
+15 -1
View File
@@ -4,12 +4,16 @@
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include <chrono>
#include <fmt/ranges.h> #include <fmt/ranges.h>
#include <string_view>
#include <thread>
#include "common/assert.h" #include "common/assert.h"
#include "common/logging.h" #include "common/logging.h"
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/ipc.h" #include "core/hle/ipc.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/service/ipc_helpers.h" #include "core/hle/service/ipc_helpers.h"
#include "core/hle/service/service.h" #include "core/hle/service/service.h"
@@ -33,6 +37,7 @@ ServiceFrameworkBase::ServiceFrameworkBase(Core::System& system_, const char* se
: SessionRequestHandler(system_.Kernel(), service_name_) : SessionRequestHandler(system_.Kernel(), service_name_)
, system{system_} , system{system_}
, service_name{service_name_} , service_name{service_name_}
, is_i_storage{std::string_view{service_name_} == "IStorage"}
, handler_invoker{handler_invoker_} , handler_invoker{handler_invoker_}
, max_sessions{max_sessions_} , max_sessions{max_sessions_}
{} {}
@@ -77,13 +82,22 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
} }
void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) { void ServiceFrameworkBase::InvokeRequest(HLERequestContext& ctx) {
auto it = handlers.find(ctx.GetCommand()); const auto command = ctx.GetCommand();
auto it = handlers.find(command);
const bool is_cmd_read = command == 0;
FunctionInfoBase const* info = it == handlers.end() ? nullptr : &it->second; FunctionInfoBase const* info = it == handlers.end() ? nullptr : &it->second;
if (info == nullptr || info->handler_callback == nullptr) if (info == nullptr || info->handler_callback == nullptr)
return ReportUnimplementedFunction(ctx, info); return ReportUnimplementedFunction(ctx, info);
LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer())); LOG_TRACE(Service, "{}", MakeFunctionString(info->name, GetServiceName(), ctx.CommandBuffer()));
handler_invoker(this, info->handler_callback, ctx); handler_invoker(this, info->handler_callback, ctx);
if (is_i_storage && is_cmd_read) {
const auto* const process = ctx.GetThread().GetOwnerProcess();
if (process != nullptr && system.IsNVDECActiveForProcess(process->GetId())) {
std::this_thread::sleep_for(std::chrono::microseconds{600});
}
}
} }
void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) { void ServiceFrameworkBase::InvokeRequestTipc(HLERequestContext& ctx) {
+2
View File
@@ -107,6 +107,8 @@ protected:
Core::System& system; Core::System& system;
/// Identifier string used to connect to the service. /// Identifier string used to connect to the service.
const char* service_name; const char* service_name;
/// Whether this is the IStorage service.
const bool is_i_storage;
/// Function used to safely up-cast pointers to the derived class before invoking a handler. /// Function used to safely up-cast pointers to the derived class before invoking a handler.
InvokerFn* handler_invoker; InvokerFn* handler_invoker;
/// Maximum number of concurrent sessions that this service can handle. /// Maximum number of concurrent sessions that this service can handle.
+90 -90
View File
@@ -54,11 +54,11 @@ void PutValue(std::span<u8> buffer, const T& t) {
} // Anonymous namespace } // 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); 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) { if (write_buffer.size() > 0) {
ctx.WriteBuffer(write_buffer); ctx.WriteBuffer(write_buffer);
} }
@@ -69,11 +69,11 @@ void NetworkBSD::PollWork::Response(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno); 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); 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) { if (write_buffer.size() > 0) {
ctx.WriteBuffer(write_buffer); ctx.WriteBuffer(write_buffer);
} }
@@ -85,22 +85,22 @@ void NetworkBSD::AcceptWork::Response(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(write_buffer.size())); 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); bsd_errno = bsd->ConnectImpl(fd, addr);
} }
void NetworkBSD::ConnectWork::Response(HLERequestContext& ctx) { void BSD::ConnectWork::Response(HLERequestContext& ctx) {
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1); rb.Push<s32>(bsd_errno == Errno::SUCCESS ? 0 : -1);
rb.PushEnum(bsd_errno); 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); 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); ctx.WriteBuffer(message);
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@@ -109,11 +109,11 @@ void NetworkBSD::RecvWork::Response(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno); 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); 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); ctx.WriteBuffer(message, 0);
if (!addr.empty()) { if (!addr.empty()) {
ctx.WriteBuffer(addr, 1); ctx.WriteBuffer(addr, 1);
@@ -126,29 +126,29 @@ void NetworkBSD::RecvFromWork::Response(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(addr.size())); 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); 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}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<s32>(ret); rb.Push<s32>(ret);
rb.PushEnum(bsd_errno); 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); 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}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
rb.Push<s32>(ret); rb.Push<s32>(ret);
rb.PushEnum(bsd_errno); rb.PushEnum(bsd_errno);
} }
void NetworkBSD::RegisterClient(HLERequestContext& ctx) { void BSD::RegisterClient(HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 3}; IPC::ResponseBuilder rb{ctx, 3};
@@ -157,7 +157,7 @@ void NetworkBSD::RegisterClient(HLERequestContext& ctx) {
rb.Push<s32>(0); // bsd errno rb.Push<s32>(0); // bsd errno
} }
void NetworkBSD::StartMonitoring(HLERequestContext& ctx) { void BSD::StartMonitoring(HLERequestContext& ctx) {
LOG_WARNING(Service, "(STUBBED) called"); LOG_WARNING(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
@@ -165,7 +165,7 @@ void NetworkBSD::StartMonitoring(HLERequestContext& ctx) {
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
} }
void NetworkBSD::Socket(HLERequestContext& ctx) { void BSD::Socket(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const u32 domain = rp.Pop<u32>(); const u32 domain = rp.Pop<u32>();
const u32 type = rp.Pop<u32>(); const u32 type = rp.Pop<u32>();
@@ -200,7 +200,7 @@ void BSD::SocketExempt(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno); rb.PushEnum(bsd_errno);
} }
void NetworkBSD::Select(HLERequestContext& ctx) { void BSD::Select(HLERequestContext& ctx) {
LOG_DEBUG(Service, "(STUBBED) called"); LOG_DEBUG(Service, "(STUBBED) called");
IPC::ResponseBuilder rb{ctx, 4}; IPC::ResponseBuilder rb{ctx, 4};
@@ -210,7 +210,7 @@ void NetworkBSD::Select(HLERequestContext& ctx) {
rb.Push<u32>(0); // bsd errno rb.Push<u32>(0); // bsd errno
} }
void NetworkBSD::Poll(HLERequestContext& ctx) { void BSD::Poll(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 nfds = rp.Pop<s32>(); const s32 nfds = rp.Pop<s32>();
const s32 timeout = 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -245,7 +245,7 @@ void NetworkBSD::Bind(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer())); BuildErrnoResponse(ctx, BindImpl(fd, ctx.ReadBuffer()));
} }
void NetworkBSD::Connect(HLERequestContext& ctx) { void BSD::Connect(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -275,7 +275,7 @@ void NetworkBSD::GetPeerName(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(write_buffer.size())); rb.Push<u32>(static_cast<u32>(write_buffer.size()));
} }
void NetworkBSD::GetSockName(HLERequestContext& ctx) { void BSD::GetSockName(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -293,7 +293,7 @@ void NetworkBSD::GetSockName(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(write_buffer.size())); rb.Push<u32>(static_cast<u32>(write_buffer.size()));
} }
void NetworkBSD::GetSockOpt(HLERequestContext& ctx) { void BSD::GetSockOpt(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
const u32 level = rp.Pop<u32>(); const u32 level = rp.Pop<u32>();
@@ -315,7 +315,7 @@ void NetworkBSD::GetSockOpt(HLERequestContext& ctx) {
rb.Push<u32>(static_cast<u32>(optval.size())); rb.Push<u32>(static_cast<u32>(optval.size()));
} }
void NetworkBSD::Listen(HLERequestContext& ctx) { void BSD::Listen(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
const s32 backlog = rp.Pop<s32>(); const s32 backlog = rp.Pop<s32>();
@@ -325,7 +325,7 @@ void NetworkBSD::Listen(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, ListenImpl(fd, backlog)); BuildErrnoResponse(ctx, ListenImpl(fd, backlog));
} }
void NetworkBSD::Fcntl(HLERequestContext& ctx) { void BSD::Fcntl(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
const s32 cmd = rp.Pop<s32>(); const s32 cmd = rp.Pop<s32>();
@@ -341,7 +341,7 @@ void NetworkBSD::Fcntl(HLERequestContext& ctx) {
rb.PushEnum(bsd_errno); rb.PushEnum(bsd_errno);
} }
void NetworkBSD::SetSockOpt(HLERequestContext& ctx) { void BSD::SetSockOpt(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -355,7 +355,7 @@ void NetworkBSD::SetSockOpt(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval)); BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
} }
void NetworkBSD::Shutdown(HLERequestContext& ctx) { void BSD::Shutdown(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -366,7 +366,7 @@ void NetworkBSD::Shutdown(HLERequestContext& ctx) {
BuildErrnoResponse(ctx, ShutdownImpl(fd, how)); BuildErrnoResponse(ctx, ShutdownImpl(fd, how));
} }
void NetworkBSD::Recv(HLERequestContext& ctx) { void BSD::Recv(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
const u32 flags = rp.Pop<u32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); 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}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -454,7 +454,7 @@ void NetworkBSD::Read(HLERequestContext& ctx) {
rb.Push<u32>(0); // bsd errno rb.Push<u32>(0); // bsd errno
} }
void NetworkBSD::Close(HLERequestContext& ctx) { void BSD::Close(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
const s32 fd = rp.Pop<s32>(); const s32 fd = rp.Pop<s32>();
@@ -464,7 +464,7 @@ void NetworkBSD::Close(HLERequestContext& ctx) {
} }
/// @brief Only bsd:s is able to dup() /// @brief Only bsd:s is able to dup()
void NetworkBSD::DuplicateSocket(HLERequestContext& ctx) { void BSD::DuplicateSocket(HLERequestContext& ctx) {
struct InputParameters { struct InputParameters {
s32 fd; s32 fd;
u64 reserved; 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}; IPC::RequestParser rp{ctx};
const u64 initval = rp.Pop<u64>(); const u64 initval = rp.Pop<u64>();
const u32 flags = rp.Pop<u32>(); const u32 flags = rp.Pop<u32>();
@@ -516,12 +516,12 @@ void NetworkBSD::EventFd(HLERequestContext& ctx) {
} }
template <typename Work> template <typename Work>
void NetworkBSD::ExecuteWork(HLERequestContext& ctx, Work work) { void BSD::ExecuteWork(HLERequestContext& ctx, Work work) {
work.Execute(this); work.Execute(this);
work.Response(ctx); 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 // user bsd:u has restrictions on SOCK_SEQPACKET and SOCK_RAW
if (is_user && (type == Type::SEQPACKET || type == Type::RAW)) { if (is_user && (type == Type::SEQPACKET || type == Type::RAW)) {
if (type == Type::RAW && domain == Domain::INET && protocol == Protocol::ICMP) { 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}; 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) { s32 nfds, s32 timeout) {
if (nfds <= 0) { if (nfds <= 0) {
// When no entries are provided, -1 is returned with errno zero // 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); 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)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; 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}; 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; 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))); 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -698,7 +698,7 @@ Errno NetworkBSD::ConnectImpl(s32 fd, std::span<const u8> addr) {
return result; 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -720,7 +720,7 @@ Errno NetworkBSD::GetPeerNameImpl(s32 fd, std::vector<u8>& write_buffer) {
return Translate(bsd_errno); 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -742,7 +742,7 @@ Errno NetworkBSD::GetSockNameImpl(s32 fd, std::vector<u8>& write_buffer) {
return Translate(bsd_errno); return Translate(bsd_errno);
} }
Errno NetworkBSD::ListenImpl(s32 fd, s32 backlog) { Errno BSD::ListenImpl(s32 fd, s32 backlog) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -753,7 +753,7 @@ Errno NetworkBSD::ListenImpl(s32 fd, s32 backlog) {
return Translate(file_descriptors[fd]->socket->Listen(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)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -884,7 +884,7 @@ Errno NetworkBSD::ShutdownImpl(s32 fd, s32 how) {
return Translate(file_descriptors[fd]->socket->Shutdown(host_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)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; 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}; 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) { std::vector<u8>& addr) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; 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}; 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)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; 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)); 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) { std::span<const u8> addr) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return {-1, Errno::BADF}; 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)); 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)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -1011,7 +1011,7 @@ Errno NetworkBSD::CloseImpl(s32 fd) {
return bsd_errno; return bsd_errno;
} }
std::variant<s32, Errno> NetworkBSD::DuplicateSocketImpl(s32 fd) { std::variant<s32, Errno> BSD::DuplicateSocketImpl(s32 fd) {
if (!IsFileDescriptorValid(fd)) { if (!IsFileDescriptorValid(fd)) {
return Errno::BADF; return Errno::BADF;
} }
@@ -1030,7 +1030,7 @@ std::variant<s32, Errno> NetworkBSD::DuplicateSocketImpl(s32 fd) {
return new_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)) { if (!IsFileDescriptorValid(fd)) {
return std::nullopt; return std::nullopt;
} }
@@ -1041,7 +1041,7 @@ std::optional<std::shared_ptr<Network::SocketBase>> NetworkBSD::GetSocket(s32 fd
return file_descriptors[fd]->socket; 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) { for (s32 fd = 0; fd < static_cast<s32>(file_descriptors.size()); ++fd) {
if (!file_descriptors[fd]) { if (!file_descriptors[fd]) {
return fd; return fd;
@@ -1050,7 +1050,7 @@ s32 NetworkBSD::FindFreeFileDescriptorHandle() noexcept {
return -1; 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) { if (fd > static_cast<s32>(MAX_FD) || fd < 0) {
LOG_ERROR(Service, "Invalid file descriptor handle={}", fd); LOG_ERROR(Service, "Invalid file descriptor handle={}", fd);
return false; return false;
@@ -1062,7 +1062,7 @@ bool NetworkBSD::IsFileDescriptorValid(s32 fd) const noexcept {
return true; 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}; IPC::ResponseBuilder rb{ctx, 4};
rb.Push(ResultSuccess); rb.Push(ResultSuccess);
@@ -1070,7 +1070,7 @@ void NetworkBSD::BuildErrnoResponse(HLERequestContext& ctx, Errno bsd_errno) con
rb.PushEnum(bsd_errno); rb.PushEnum(bsd_errno);
} }
void NetworkBSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) { void BSD::OnProxyPacketReceived(const Network::ProxyPacket& packet) {
for (auto& optional_descriptor : file_descriptors) { for (auto& optional_descriptor : file_descriptors) {
if (!optional_descriptor.has_value()) { if (!optional_descriptor.has_value()) {
continue; 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} : ServiceFramework{system_, name}
, is_user{is_user_} { , is_user{is_user_} {
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &NetworkBSD::RegisterClient, "RegisterClient"}, {0, &BSD::RegisterClient, "RegisterClient"},
{1, &NetworkBSD::StartMonitoring, "StartMonitoring"}, {1, &BSD::StartMonitoring, "StartMonitoring"},
{2, &NetworkBSD::Socket, "Socket"}, {2, &BSD::Socket, "Socket"},
{3, &NetworkBSD::SocketExempt, "SocketExempt"}, {3, &BSD::SocketExempt, "SocketExempt"},
{4, nullptr, "Open"}, {4, nullptr, "Open"},
{5, &NetworkBSD::Select, "Select"}, {5, &BSD::Select, "Select"},
{6, &NetworkBSD::Poll, "Poll"}, {6, &BSD::Poll, "Poll"},
{7, nullptr, "Sysctl"}, {7, nullptr, "Sysctl"},
{8, &NetworkBSD::Recv, "Recv"}, {8, &BSD::Recv, "Recv"},
{9, &NetworkBSD::RecvFrom, "RecvFrom"}, {9, &BSD::RecvFrom, "RecvFrom"},
{10, &NetworkBSD::Send, "Send"}, {10, &BSD::Send, "Send"},
{11, &NetworkBSD::SendTo, "SendTo"}, {11, &BSD::SendTo, "SendTo"},
{12, &NetworkBSD::Accept, "Accept"}, {12, &BSD::Accept, "Accept"},
{13, &NetworkBSD::Bind, "Bind"}, {13, &BSD::Bind, "Bind"},
{14, &NetworkBSD::Connect, "Connect"}, {14, &BSD::Connect, "Connect"},
{15, &NetworkBSD::GetPeerName, "GetPeerName"}, {15, &BSD::GetPeerName, "GetPeerName"},
{16, &NetworkBSD::GetSockName, "GetSockName"}, {16, &BSD::GetSockName, "GetSockName"},
{17, &NetworkBSD::GetSockOpt, "GetSockOpt"}, {17, &BSD::GetSockOpt, "GetSockOpt"},
{18, &NetworkBSD::Listen, "Listen"}, {18, &BSD::Listen, "Listen"},
{19, nullptr, "Ioctl"}, {19, nullptr, "Ioctl"},
{20, &NetworkBSD::Fcntl, "Fcntl"}, {20, &BSD::Fcntl, "Fcntl"},
{21, &NetworkBSD::SetSockOpt, "SetSockOpt"}, {21, &BSD::SetSockOpt, "SetSockOpt"},
{22, &NetworkBSD::Shutdown, "Shutdown"}, {22, &BSD::Shutdown, "Shutdown"},
{23, nullptr, "ShutdownAllSockets"}, {23, nullptr, "ShutdownAllSockets"},
{24, &NetworkBSD::Write, "Write"}, {24, &BSD::Write, "Write"},
{25, &NetworkBSD::Read, "Read"}, {25, &BSD::Read, "Read"},
{26, &NetworkBSD::Close, "Close"}, {26, &BSD::Close, "Close"},
{27, &NetworkBSD::DuplicateSocket, "DuplicateSocket"}, {27, &BSD::DuplicateSocket, "DuplicateSocket"},
{28, nullptr, "GetResourceStatistics"}, {28, nullptr, "GetResourceStatistics"},
{29, nullptr, "RecvMMsg"}, //3.0.0+ {29, nullptr, "RecvMMsg"}, //3.0.0+
{30, nullptr, "SendMMsg"}, //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+ {32, nullptr, "RegisterResourceStatisticsName"}, //7.0.0+
{33, nullptr, "RegisterClientShared"}, //10.0.0+ {33, nullptr, "RegisterClientShared"}, //10.0.0+
{34, nullptr, "GetSocketStatistics"}, //15.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()) { if (auto room_member = Network::GetRoomMember().lock()) {
room_member->Unbind(proxy_packet_received); room_member->Unbind(proxy_packet_received);
} }
} }
std::unique_lock<std::mutex> NetworkBSD::LockService() noexcept { std::unique_lock<std::mutex> BSD::LockService() noexcept {
return {}; return {};
} }
+10 -10
View File
@@ -27,10 +27,10 @@ class Socket;
namespace Service::Sockets { namespace Service::Sockets {
class NetworkBSD final : public ServiceFramework<NetworkBSD> { class BSD final : public ServiceFramework<BSD> {
public: public:
explicit NetworkBSD(Core::System& system_, const char* name, bool is_user); explicit BSD(Core::System& system_, const char* name, bool is_user);
~NetworkBSD() override; ~BSD() override;
// These methods are called from SSL; the first two are also called from // These methods are called from SSL; the first two are also called from
// this class for the corresponding IPC methods. // this class for the corresponding IPC methods.
@@ -50,7 +50,7 @@ private:
}; };
struct PollWork { struct PollWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 nfds; s32 nfds;
@@ -62,7 +62,7 @@ private:
}; };
struct AcceptWork { struct AcceptWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 fd; s32 fd;
@@ -72,7 +72,7 @@ private:
}; };
struct ConnectWork { struct ConnectWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 fd; s32 fd;
@@ -81,7 +81,7 @@ private:
}; };
struct RecvWork { struct RecvWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 fd; s32 fd;
@@ -92,7 +92,7 @@ private:
}; };
struct RecvFromWork { struct RecvFromWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 fd; s32 fd;
@@ -104,7 +104,7 @@ private:
}; };
struct SendWork { struct SendWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 fd; s32 fd;
@@ -115,7 +115,7 @@ private:
}; };
struct SendToWork { struct SendToWork {
void Execute(NetworkBSD* bsd); void Execute(BSD* bsd);
void Response(HLERequestContext& ctx); void Response(HLERequestContext& ctx);
s32 fd; 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:c", std::make_shared<ETHC_C>(system));
server_manager->RegisterNamedService("ethc:i", std::make_shared<ETHC_I>(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:s", std::make_shared<BSD>(system, "bsd:s", false));
server_manager->RegisterNamedService("bsd:u", std::make_shared<NetworkBSD>(system, "bsd:u", true)); server_manager->RegisterNamedService("bsd:u", std::make_shared<BSD>(system, "bsd:u", true));
server_manager->RegisterNamedService("bsd:a", std::make_shared<NetworkBSD>(system, "bsd:a", 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("bsd:nu", std::make_shared<BSD_NU>(system));
server_manager->RegisterNamedService("bsdcfg", std::make_shared<BSDCFG>(system, "bsdcfg")); server_manager->RegisterNamedService("bsdcfg", std::make_shared<BSDCFG>(system, "bsdcfg"));
server_manager->RegisterNamedService("ifcfg", std::make_shared<BSDCFG>(system, "ifcfg")); server_manager->RegisterNamedService("ifcfg", std::make_shared<BSDCFG>(system, "ifcfg"));
+2 -2
View File
@@ -129,7 +129,7 @@ public:
LOG_ERROR(Service_SSL, LOG_ERROR(Service_SSL,
"do_not_close_socket was changed after setting socket; is this right?"); "do_not_close_socket was changed after setting socket; is this right?");
} else { } else {
auto bsd = system.ServiceManager().GetService<Service::Sockets::NetworkBSD>("bsd:u"); auto bsd = system.ServiceManager().GetService<Service::Sockets::BSD>("bsd:u");
if (bsd) { if (bsd) {
auto err = bsd->CloseImpl(fd); auto err = bsd->CloseImpl(fd);
if (err != Service::Sockets::Errno::SUCCESS) { if (err != Service::Sockets::Errno::SUCCESS) {
@@ -157,7 +157,7 @@ private:
Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) { Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) {
LOG_DEBUG(Service_SSL, "called, fd={}", fd); LOG_DEBUG(Service_SSL, "called, fd={}", fd);
ASSERT(!did_handshake); 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; }); ASSERT_OR_EXECUTE(bsd, { return ResultInternalError; });
auto const res_v = bsd->DuplicateSocketImpl(fd); auto const res_v = bsd->DuplicateSocketImpl(fd);
+6 -4
View File
@@ -17,9 +17,11 @@
namespace Loader { namespace Loader {
[[nodiscard]] inline constexpr u32 PageAlignSizeKIP(u32 size) { namespace {
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
AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_) AppLoader_KIP::AppLoader_KIP(FileSys::VirtualFile file_)
: AppLoader(std::move(file_)), kip(std::make_unique<FileSys::KIP>(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()); kip->GetKernelCapabilities());
Kernel::CodeSet codeset; 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) { const auto load_segment = [&codeset](Kernel::CodeSet::Segment& segment, std::span<const u8> data, u32 offset) {
segment.addr = offset; segment.addr = offset;
segment.offset = 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()); std::memcpy(codeset.memory.data() + offset, data.data(), data.size());
}; };
load_segment(codeset.CodeSegment(), kip->GetTextSection(), kip->GetTextOffset()); 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'); nro_header.magic_ext2 == Common::MakeMagic('B', 'R', 'E', 'W');
} }
[[nodiscard]] inline constexpr u32 PageAlignSizeNRO(u32 size) { static constexpr u32 PageAlignSize(u32 size) {
return u32((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
} }
static bool LoadNroImpl(Core::System& system, Kernel::KProcess& process, 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 // 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()); 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 {}; 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) { for (std::size_t i = 0; i < nro_header.segments.size(); ++i) {
codeset.segments[i].addr = nro_header.segments[i].offset; codeset.segments[i].addr = nro_header.segments[i].offset;
codeset.segments[i].offset = 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 // 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 // Read MOD header
ModHeader 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')}; const bool has_mod_header{mod_header.magic == Common::MakeMagic('M', 'O', 'D', '0')};
if (has_mod_header) { if (has_mod_header) {
// Resize program image to include .bss section and page align each section // 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; codeset.DataSegment().size += bss_size;
+4 -4
View File
@@ -41,8 +41,8 @@ struct MODHeader {
}; };
static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size."); static_assert(sizeof(MODHeader) == 0x1c, "MODHeader has incorrect size.");
[[nodiscard]] inline constexpr u32 PageAlignSizeNSO(u32 size) { constexpr u32 PageAlignSize(u32 size) {
return u32((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK); return static_cast<u32>((size + Core::Memory::YUZU_PAGEMASK) & ~Core::Memory::YUZU_PAGEMASK);
} }
} // Anonymous namespace } // 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; 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); codeset.memory.resize(image_size);
for (std::size_t i = 0; i < nso_header.segments.size(); ++i) { 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 // Apply patches if necessary
-2
View File
@@ -21,8 +21,6 @@
#include "hid_core/resource_manager.h" #include "hid_core/resource_manager.h"
#include "hid_core/resources/npad/npad.h" #include "hid_core/resources/npad/npad.h"
#undef CreateEvent
namespace Core::Memory { namespace Core::Memory {
namespace { namespace {
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12}; constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
-2
View File
@@ -28,8 +28,6 @@
#include "core/memory.h" #include "core/memory.h"
#include "core/reporter.h" #include "core/reporter.h"
#undef far
namespace { namespace {
std::filesystem::path GetPath(std::string_view type, u64 title_id, std::string_view timestamp) { 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 } // Anonymous namespace
#undef CreateEvent
Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_) Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_)
: core_timing{core_timing_}, memory{memory_} { : core_timing{core_timing_}, memory{memory_} {
event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback", event = Core::Timing::CreateEvent("MemoryFreezer::FrameCallback",
@@ -31,7 +31,7 @@ using namespace oaknut::util;
namespace { 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; return acctype == IR::AccType::ORDERED || acctype == IR::AccType::ORDEREDRW || acctype == IR::AccType::LIMITEDORDERED;
} }
@@ -247,7 +247,7 @@ void A32EmitX64::GenTerminalHandlers() {
calculate_location_descriptor(); calculate_location_descriptor();
code.mov(eax, dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)]); code.mov(eax, dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)]);
code.sub(eax, 1); code.sub(eax, 1);
code.and_(eax, u32(A32JitState::RSBPtrMask)); code.and_(eax, u32(A32JitState::RSB_PTR_MASK));
code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)], eax); code.mov(dword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_ptr)], eax);
code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]); code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A32JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) { if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
@@ -37,9 +37,9 @@ using namespace Backend::X64;
static RunCodeCallbacks GenRunCodeCallbacks(A32::UserCallbacks* cb, CodePtr (*LookupBlock)(void* lookup_block_arg), void* arg, const A32::UserConfig& conf) { static RunCodeCallbacks GenRunCodeCallbacks(A32::UserCallbacks* cb, CodePtr (*LookupBlock)(void* lookup_block_arg), void* arg, const A32::UserConfig& conf) {
return RunCodeCallbacks{ return RunCodeCallbacks{
std::make_unique<ArgCallback>(LookupBlock, reinterpret_cast<u64>(arg)), ArgCallback(LookupBlock, reinterpret_cast<u64>(arg)),
std::make_unique<ArgCallback>(Devirtualize<&A32::UserCallbacks::AddTicks>(cb)), ArgCallback(Devirtualize<&A32::UserCallbacks::AddTicks>(cb)),
std::make_unique<ArgCallback>(Devirtualize<&A32::UserCallbacks::GetTicksRemaining>(cb)), ArgCallback(Devirtualize<&A32::UserCallbacks::GetTicksRemaining>(cb)),
conf.enable_cycle_counting, conf.enable_cycle_counting,
}; };
} }
@@ -79,7 +79,7 @@ struct Jit::Impl {
jit_interface->is_executing = true; jit_interface->is_executing = true;
const CodePtr current_codeptr = [this] { const CodePtr current_codeptr = [this] {
// RSB optimization // RSB optimization
const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A32JitState::RSBPtrMask; const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A32JitState::RSB_PTR_MASK;
if (jit_state.GetUniqueHash() == jit_state.rsb_location_descriptors[new_rsb_ptr]) { if (jit_state.GetUniqueHash() == jit_state.rsb_location_descriptors[new_rsb_ptr]) {
jit_state.rsb_ptr = new_rsb_ptr; jit_state.rsb_ptr = new_rsb_ptr;
return reinterpret_cast<CodePtr>(jit_state.rsb_codeptrs[new_rsb_ptr]); return reinterpret_cast<CodePtr>(jit_state.rsb_codeptrs[new_rsb_ptr]);
@@ -27,6 +27,9 @@ struct A32JitState {
A32JitState() { ResetRSB(); } A32JitState() { ResetRSB(); }
static constexpr std::size_t RSB_SIZE = 8; // MUST be a power of 2.
static constexpr std::size_t RSB_PTR_MASK = RSB_SIZE - 1;
std::array<u32, 16> Reg{}; // Current register file. std::array<u32, 16> Reg{}; // Current register file.
// TODO: Mode-specific register sets unimplemented. // TODO: Mode-specific register sets unimplemented.
@@ -36,8 +39,9 @@ struct A32JitState {
u32 cpsr_q = 0; u32 cpsr_q = 0;
u32 cpsr_nzcv = 0; u32 cpsr_nzcv = 0;
u32 cpsr_jaifm = 0; u32 cpsr_jaifm = 0;
u32 Cpsr() const; u32 fpsr_exc = 0;
void SetCpsr(u32 cpsr); u32 fpsr_qc = 0;
u32 fpsr_nzcv = 0;
alignas(16) std::array<u32, 64> ExtReg{}; // Extension registers. alignas(16) std::array<u32, 64> ExtReg{}; // Extension registers.
@@ -49,21 +53,19 @@ struct A32JitState {
// Exclusive state // Exclusive state
u32 exclusive_state = 0; u32 exclusive_state = 0;
static constexpr std::size_t RSBSize = 8; // MUST be a power of 2.
static constexpr std::size_t RSBPtrMask = RSBSize - 1;
u32 rsb_ptr = 0; u32 rsb_ptr = 0;
std::array<u64, RSBSize> rsb_location_descriptors; std::array<u64, RSB_SIZE> rsb_location_descriptors;
std::array<u64, RSBSize> rsb_codeptrs; std::array<u64, RSB_SIZE> rsb_codeptrs;
void ResetRSB();
u32 fpsr_exc = 0; u32 Cpsr() const;
u32 fpsr_qc = 0; void SetCpsr(u32 cpsr);
u32 fpsr_nzcv = 0;
void ResetRSB();
u32 Fpscr() const; u32 Fpscr() const;
void SetFpscr(u32 FPSCR); void SetFpscr(u32 FPSCR);
u64 GetUniqueHash() const noexcept { u64 GetUniqueHash() const noexcept {
return (static_cast<u64>(upper_location_descriptor) << 32) | (static_cast<u64>(Reg[15])); return (u64(upper_location_descriptor) << 32) | (u64(Reg[15]));
} }
void TransferJitState(const A32JitState& src, bool reset_rsb) { void TransferJitState(const A32JitState& src, bool reset_rsb) {
@@ -208,7 +208,7 @@ void A64EmitX64::GenTerminalHandlers() {
calculate_location_descriptor(); calculate_location_descriptor();
code.mov(eax, dword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_ptr)]); code.mov(eax, dword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_ptr)]);
code.sub(eax, 1); code.sub(eax, 1);
code.and_(eax, u32(A64JitState::RSBPtrMask)); code.and_(eax, u32(A64JitState::RSB_PTR_MASK));
code.mov(dword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_ptr)], eax); code.mov(dword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_ptr)], eax);
code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]); code.cmp(rbx, qword[code.ABI_JIT_PTR + offsetof(A64JitState, rsb_location_descriptors) + rax * sizeof(u64)]);
if (conf.HasOptimization(OptimizationFlag::FastDispatch)) { if (conf.HasOptimization(OptimizationFlag::FastDispatch)) {
@@ -33,9 +33,9 @@ using namespace Backend::X64;
static RunCodeCallbacks GenRunCodeCallbacks(A64::UserCallbacks* cb, CodePtr (*LookupBlock)(void* lookup_block_arg), void* arg, const A64::UserConfig& conf) { static RunCodeCallbacks GenRunCodeCallbacks(A64::UserCallbacks* cb, CodePtr (*LookupBlock)(void* lookup_block_arg), void* arg, const A64::UserConfig& conf) {
return RunCodeCallbacks{ return RunCodeCallbacks{
std::make_unique<ArgCallback>(LookupBlock, reinterpret_cast<u64>(arg)), ArgCallback(LookupBlock, reinterpret_cast<u64>(arg)),
std::make_unique<ArgCallback>(Devirtualize<&A64::UserCallbacks::AddTicks>(cb)), ArgCallback(Devirtualize<&A64::UserCallbacks::AddTicks>(cb)),
std::make_unique<ArgCallback>(Devirtualize<&A64::UserCallbacks::GetTicksRemaining>(cb)), ArgCallback(Devirtualize<&A64::UserCallbacks::GetTicksRemaining>(cb)),
conf.enable_cycle_counting, conf.enable_cycle_counting,
}; };
} }
@@ -78,7 +78,7 @@ public:
// TODO: Check code alignment // TODO: Check code alignment
const CodePtr current_code_ptr = [this] { const CodePtr current_code_ptr = [this] {
// RSB optimization // RSB optimization
const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A64JitState::RSBPtrMask; const u32 new_rsb_ptr = (jit_state.rsb_ptr - 1) & A64JitState::RSB_PTR_MASK;
if (jit_state.GetUniqueHash() == jit_state.rsb_location_descriptors[new_rsb_ptr]) { if (jit_state.GetUniqueHash() == jit_state.rsb_location_descriptors[new_rsb_ptr]) {
jit_state.rsb_ptr = new_rsb_ptr; jit_state.rsb_ptr = new_rsb_ptr;
return CodePtr(jit_state.rsb_codeptrs[new_rsb_ptr]); return CodePtr(jit_state.rsb_codeptrs[new_rsb_ptr]);
@@ -29,18 +29,19 @@ struct A64JitState {
A64JitState() { ResetRSB(); } A64JitState() { ResetRSB(); }
// Exclusive state stuff
static constexpr u64 RESERVATION_GRANULE_MASK = 0xFFFF'FFFF'FFFF'FFF0ull;
// Return stack buffer
static constexpr size_t RSB_SIZE = 8; // MUST be a power of 2.
static constexpr size_t RSB_PTR_MASK = RSB_SIZE - 1;
std::array<u64, 31> reg{}; std::array<u64, 31> reg{};
u64 sp = 0; u64 sp = 0;
u64 pc = 0; u64 pc = 0;
u32 cpsr_nzcv = 0; u32 cpsr_nzcv = 0;
u32 fpsr_exc = 0;
u32 GetPstate() const { u32 fpsr_qc = 0;
return NZCV::FromX64(cpsr_nzcv); u32 fpcr = 0;
}
void SetPstate(u32 new_pstate) {
cpsr_nzcv = NZCV::ToX64(new_pstate);
}
alignas(16) std::array<u64, 64> vec{}; // Extension registers. alignas(16) std::array<u64, 64> vec{}; // Extension registers.
@@ -50,29 +51,31 @@ struct A64JitState {
volatile u32 halt_reason = 0; volatile u32 halt_reason = 0;
// Exclusive state // Exclusive state
static constexpr u64 RESERVATION_GRANULE_MASK = 0xFFFF'FFFF'FFFF'FFF0ull;
u8 exclusive_state = 0; u8 exclusive_state = 0;
static constexpr size_t RSBSize = 8; // MUST be a power of 2.
static constexpr size_t RSBPtrMask = RSBSize - 1;
u32 rsb_ptr = 0; u32 rsb_ptr = 0;
std::array<u64, RSBSize> rsb_location_descriptors; std::array<u64, RSB_SIZE> rsb_location_descriptors;
std::array<u64, RSBSize> rsb_codeptrs; std::array<u64, RSB_SIZE> rsb_codeptrs;
u32 GetPstate() const {
return NZCV::FromX64(cpsr_nzcv);
}
void SetPstate(u32 new_pstate) {
cpsr_nzcv = NZCV::ToX64(new_pstate);
}
void ResetRSB() { void ResetRSB() {
rsb_location_descriptors.fill(0xFFFFFFFFFFFFFFFFull); rsb_location_descriptors.fill(0xFFFFFFFFFFFFFFFFull);
rsb_codeptrs.fill(0); rsb_codeptrs.fill(0);
} }
u32 fpsr_exc = 0;
u32 fpsr_qc = 0;
u32 fpcr = 0;
u32 GetFpcr() const; u32 GetFpcr() const;
u32 GetFpsr() const; u32 GetFpsr() const;
void SetFpcr(u32 value); void SetFpcr(u32 value);
void SetFpsr(u32 value); void SetFpsr(u32 value);
u64 GetUniqueHash() const noexcept { u64 GetUniqueHash() const noexcept {
const u64 fpcr_u64 = static_cast<u64>(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift; const u64 fpcr_u64 = u64(fpcr & A64::LocationDescriptor::fpcr_mask) << A64::LocationDescriptor::fpcr_shift;
const u64 pc_u64 = pc & A64::LocationDescriptor::pc_mask; const u64 pc_u64 = pc & A64::LocationDescriptor::pc_mask;
return pc_u64 | fpcr_u64; return pc_u64 | fpcr_u64;
} }
@@ -61,73 +61,6 @@ namespace {
constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024; constexpr size_t CONSTANT_POOL_SIZE = 2 * 1024 * 1024;
constexpr size_t PRELUDE_COMMIT_SIZE = 16 * 1024 * 1024; constexpr size_t PRELUDE_COMMIT_SIZE = 16 * 1024 * 1024;
class CustomXbyakAllocator : public Xbyak::Allocator {
public:
#ifdef _WIN32
uint8_t* alloc(size_t size) override {
void* p = VirtualAlloc(nullptr, size, MEM_RESERVE, PAGE_READWRITE);
if (p == nullptr) {
using Xbyak::Error;
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
}
return static_cast<uint8_t*>(p);
}
void free(uint8_t* p) override {
VirtualFree(static_cast<void*>(p), 0, MEM_RELEASE);
}
bool useProtect() const override { return false; }
#else
static constexpr size_t DYNARMIC_PAGE_SIZE = 4096;
// Can't subclass Xbyak::MmapAllocator because it is not a pure interface
// and doesn't expose its construtor
uint8_t* alloc(size_t size) override {
// Waste a page to store the size
size += DYNARMIC_PAGE_SIZE;
int mode = MAP_PRIVATE;
#if defined(MAP_ANONYMOUS)
mode |= MAP_ANONYMOUS;
#elif defined(MAP_ANON)
mode |= MAP_ANON;
#else
# error "not supported"
#endif
#ifdef MAP_JIT
mode |= MAP_JIT;
#endif
int prot = PROT_READ | PROT_WRITE;
#ifdef PROT_MPROTECT
// https://man.netbsd.org/mprotect.2 specifies that an mprotect() that is LESS
// restrictive than the original mapping MUST fail
prot |= PROT_MPROTECT(PROT_READ) | PROT_MPROTECT(PROT_WRITE) | PROT_MPROTECT(PROT_EXEC);
#endif
void* p = mmap(nullptr, size, prot, mode, -1, 0);
if (p == MAP_FAILED) {
using Xbyak::Error;
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);
}
std::memcpy(p, &size, sizeof(size_t));
return static_cast<uint8_t*>(p) + DYNARMIC_PAGE_SIZE;
}
void free(uint8_t* p) override {
size_t size;
std::memcpy(&size, p - DYNARMIC_PAGE_SIZE, sizeof(size_t));
munmap(p - DYNARMIC_PAGE_SIZE, size);
}
# ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
bool useProtect() const override { return false; }
# endif
#endif
};
// This is threadsafe as Xbyak::Allocator does not contain any state; it is a pure interface.
CustomXbyakAllocator s_allocator;
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT #ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
void ProtectMemory(const void* base, size_t size, bool is_executable) { void ProtectMemory(const void* base, size_t size, bool is_executable) {
# ifdef _WIN32 # ifdef _WIN32
@@ -145,11 +78,9 @@ void ProtectMemory(const void* base, size_t size, bool is_executable) {
HostFeature GetHostFeatures() { HostFeature GetHostFeatures() {
HostFeature features = {}; HostFeature features = {};
#ifdef DYNARMIC_ENABLE_CPU_FEATURE_DETECTION #ifdef DYNARMIC_ENABLE_CPU_FEATURE_DETECTION
using Cpu = Xbyak::util::Cpu; using Cpu = Xbyak::util::Cpu;
Xbyak::util::Cpu cpu_info; Xbyak::util::Cpu cpu_info{};
if (cpu_info.has(Cpu::tSSSE3)) if (cpu_info.has(Cpu::tSSSE3))
features |= HostFeature::SSSE3; features |= HostFeature::SSSE3;
if (cpu_info.has(Cpu::tSSE41)) if (cpu_info.has(Cpu::tSSE41))
@@ -196,7 +127,6 @@ HostFeature GetHostFeatures() {
features |= HostFeature::GFNI; features |= HostFeature::GFNI;
if (cpu_info.has(Cpu::tWAITPKG)) if (cpu_info.has(Cpu::tWAITPKG))
features |= HostFeature::WAITPKG; features |= HostFeature::WAITPKG;
if (cpu_info.has(Cpu::tBMI2)) { if (cpu_info.has(Cpu::tBMI2)) {
// BMI2 instructions such as pdep and pext have been very slow up until Zen 3. // BMI2 instructions such as pdep and pext have been very slow up until Zen 3.
// Check for Zen 3 or newer by its family (0x19). // Check for Zen 3 or newer by its family (0x19).
@@ -214,7 +144,6 @@ HostFeature GetHostFeatures() {
} }
} }
#endif #endif
return features; return features;
} }
@@ -233,23 +162,27 @@ bool IsUnderRosetta() {
} // anonymous namespace } // anonymous namespace
#ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
static const auto default_cg_mode = Xbyak::DontSetProtectRWE;
#else
static const auto default_cg_mode = nullptr; //Allow RWE
#endif
BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, std::function<void(BlockOfCode&)> rcp) BlockOfCode::BlockOfCode(RunCodeCallbacks cb, JitStateInfo jsi, size_t total_code_size, std::function<void(BlockOfCode&)> rcp)
: Xbyak::CodeGenerator(total_code_size, default_cg_mode, &s_allocator) : Xbyak::CodeGenerator(total_code_size
, cb(std::move(cb)) #ifdef DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT
, jsi(jsi) , Xbyak::DontSetProtectRWE
, constant_pool(*this, CONSTANT_POOL_SIZE) #else
, host_features(GetHostFeatures()) { , nullptr //Allow RWE
#endif
, nullptr)
, constant_pool(*this, CONSTANT_POOL_SIZE)
, jsi(jsi)
, cb(std::move(cb))
{
EnableWriting(); EnableWriting();
EnsureMemoryCommitted(PRELUDE_COMMIT_SIZE); EnsureMemoryCommitted(PRELUDE_COMMIT_SIZE);
GenRunCode(rcp); GenRunCode(rcp);
} }
bool BlockOfCode::HasHostFeature(HostFeature feature) const noexcept {
return (GetHostFeatures() & feature) == feature;
}
void BlockOfCode::PreludeComplete() { void BlockOfCode::PreludeComplete() {
prelude_complete = true; prelude_complete = true;
code_begin = getCurr(); code_begin = getCurr();
@@ -341,7 +274,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
mov(rbx, ABI_PARAM2); // save temporarily in non-volatile register mov(rbx, ABI_PARAM2); // save temporarily in non-volatile register
if (cb.enable_cycle_counting) { if (cb.enable_cycle_counting) {
cb.GetTicksRemaining->EmitCall(*this); cb.GetTicksRemaining.EmitCall(*this);
mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)], ABI_RETURN); mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)], ABI_RETURN);
mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], ABI_RETURN); mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], ABI_RETURN);
} }
@@ -388,7 +321,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0); cmp(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], 0);
jng(return_to_caller); jng(return_to_caller);
} }
cb.LookupBlock->EmitCall(*this); cb.LookupBlock.EmitCall(*this);
jmp(ABI_RETURN); jmp(ABI_RETURN);
align(); align();
@@ -401,7 +334,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
jng(return_to_caller_mxcsr_already_exited); jng(return_to_caller_mxcsr_already_exited);
} }
SwitchMxcsrOnEntry(); SwitchMxcsrOnEntry();
cb.LookupBlock->EmitCall(*this); cb.LookupBlock.EmitCall(*this);
jmp(ABI_RETURN); jmp(ABI_RETURN);
align(); align();
@@ -415,7 +348,7 @@ void BlockOfCode::GenRunCode(std::function<void(BlockOfCode&)> rcp) {
L(return_to_caller_mxcsr_already_exited); L(return_to_caller_mxcsr_already_exited);
if (cb.enable_cycle_counting) { if (cb.enable_cycle_counting) {
cb.AddTicks->EmitCall(*this, [this](RegList param) { cb.AddTicks.EmitCall(*this, [this](RegList param) {
mov(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)]); mov(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)]);
sub(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)]); sub(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)]);
}); });
@@ -455,18 +388,18 @@ void BlockOfCode::UpdateTicks() {
return; return;
} }
cb.AddTicks->EmitCall(*this, [this](RegList param) { cb.AddTicks.EmitCall(*this, [this](RegList param) {
mov(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)]); mov(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)]);
sub(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)]); sub(param[0], qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)]);
}); });
cb.GetTicksRemaining->EmitCall(*this); cb.GetTicksRemaining.EmitCall(*this);
mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)], ABI_RETURN); mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_to_run)], ABI_RETURN);
mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], ABI_RETURN); mov(qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, cycles_remaining)], ABI_RETURN);
} }
void BlockOfCode::LookupBlock() { void BlockOfCode::LookupBlock() {
cb.LookupBlock->EmitCall(*this); cb.LookupBlock.EmitCall(*this);
} }
void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) { void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) {
@@ -520,7 +453,7 @@ void BlockOfCode::LoadRequiredFlagsForCondFromRax(IR::Cond cond) {
} }
Xbyak::Address BlockOfCode::Const(const Xbyak::AddressFrame& frame, u64 lower, u64 upper) { Xbyak::Address BlockOfCode::Const(const Xbyak::AddressFrame& frame, u64 lower, u64 upper) {
return constant_pool.GetConstant(frame, lower, upper); return constant_pool.GetConstant(*this, frame, lower, upper);
} }
CodePtr BlockOfCode::GetCodeBegin() const { CodePtr BlockOfCode::GetCodeBegin() const {
@@ -31,9 +31,9 @@ namespace Dynarmic::Backend::X64 {
using CodePtr = const void*; using CodePtr = const void*;
struct RunCodeCallbacks { struct RunCodeCallbacks {
std::unique_ptr<Callback> LookupBlock; ArgCallback LookupBlock;
std::unique_ptr<Callback> AddTicks; ArgCallback AddTicks;
std::unique_ptr<Callback> GetTicksRemaining; ArgCallback GetTicksRemaining;
bool enable_cycle_counting; bool enable_cycle_counting;
}; };
@@ -166,27 +166,24 @@ public:
JitStateInfo GetJitStateInfo() const { return jsi; } JitStateInfo GetJitStateInfo() const { return jsi; }
bool HasHostFeature(HostFeature feature) const { bool HasHostFeature(HostFeature feature) const noexcept;
return (host_features & feature) == feature;
}
private: private:
using RunCodeFuncType = HaltReason (*)(void*, CodePtr); using RunCodeFuncType = HaltReason (*)(void*, CodePtr);
static constexpr size_t MXCSR_ALREADY_EXITED = 1 << 0; static constexpr size_t MXCSR_ALREADY_EXITED = 1 << 0;
static constexpr size_t FORCE_RETURN = 1 << 1; static constexpr size_t FORCE_RETURN = 1 << 1;
RunCodeCallbacks cb; ConstantPool constant_pool;
JitStateInfo jsi; JitStateInfo jsi;
std::array<const void*, 4> return_from_run_code;
RunCodeFuncType run_code = nullptr;
RunCodeFuncType step_code = nullptr;
RunCodeCallbacks cb;
CodePtr code_begin = nullptr; CodePtr code_begin = nullptr;
#ifdef _WIN32 #ifdef _WIN32
size_t committed_size = 0; size_t committed_size = 0;
#endif #endif
ConstantPool constant_pool;
RunCodeFuncType run_code = nullptr;
RunCodeFuncType step_code = nullptr;
std::array<const void*, 4> return_from_run_code;
bool prelude_complete = false; bool prelude_complete = false;
const HostFeature host_features;
void GenRunCode(std::function<void(BlockOfCode&)> rcp); void GenRunCode(std::function<void(BlockOfCode&)> rcp);
}; };
@@ -16,8 +16,7 @@
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
ConstantPool::ConstantPool(BlockOfCode& code, size_t size) ConstantPool::ConstantPool(BlockOfCode& code, size_t size)
: code(code) : insertion_point(0)
, insertion_point(0)
{ {
code.EnsureMemoryCommitted(align_size + size); code.EnsureMemoryCommitted(align_size + size);
code.int3(); code.int3();
@@ -25,17 +24,17 @@ ConstantPool::ConstantPool(BlockOfCode& code, size_t size)
pool = std::span<ConstantT>(reinterpret_cast<ConstantT*>(code.AllocateFromCodeSpace(size)), size / align_size); pool = std::span<ConstantT>(reinterpret_cast<ConstantT*>(code.AllocateFromCodeSpace(size)), size / align_size);
} }
Xbyak::Address ConstantPool::GetConstant(const Xbyak::AddressFrame& frame, u64 lower, u64 upper) { Xbyak::Address ConstantPool::GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper) {
const auto constant = ConstantT(lower, upper); const auto constant = ConstantT(lower, upper);
auto iter = constant_info.find(constant); auto it = constant_info.find(constant);
if (iter == constant_info.end()) { if (it == constant_info.end()) {
ASSERT(insertion_point < pool.size()); ASSERT(insertion_point < pool.size());
ConstantT& target_constant = pool[insertion_point]; ConstantT& target_constant = pool[insertion_point];
target_constant = constant; target_constant = constant;
iter = constant_info.insert({constant, &target_constant}).first; it = constant_info.insert({constant, &target_constant}).first;
++insertion_point; ++insertion_point;
} }
return frame[code.rip + iter->second]; return frame[code.rip + it->second];
} }
} // namespace Dynarmic::Backend::X64 } // namespace Dynarmic::Backend::X64
@@ -29,7 +29,7 @@ class ConstantPool final {
public: public:
ConstantPool(BlockOfCode& code, size_t size); ConstantPool(BlockOfCode& code, size_t size);
Xbyak::Address GetConstant(const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0); Xbyak::Address GetConstant(BlockOfCode& code, const Xbyak::AddressFrame& frame, u64 lower, u64 upper = 0);
private: private:
static constexpr size_t align_size = 16; // bytes static constexpr size_t align_size = 16; // bytes
@@ -45,7 +45,6 @@ private:
ankerl::unordered_dense::map<ConstantT, void*, ConstantHash> constant_info; ankerl::unordered_dense::map<ConstantT, void*, ConstantHash> constant_info;
std::span<ConstantT> pool; std::span<ConstantT> pool;
BlockOfCode& code;
std::size_t insertion_point; std::size_t insertion_point;
}; };
@@ -12,7 +12,7 @@
namespace Dynarmic::Backend::X64 { namespace Dynarmic::Backend::X64 {
enum class HostFeature : u64 { enum class HostFeature : u32 {
SSSE3 = 1ULL << 0, SSSE3 = 1ULL << 0,
SSE41 = 1ULL << 1, SSE41 = 1ULL << 1,
SSE42 = 1ULL << 2, SSE42 = 1ULL << 2,
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project. /* This file is part of the dynarmic project.
* Copyright (c) 2016 MerryMage * Copyright (c) 2016 MerryMage
* SPDX-License-Identifier: 0BSD * SPDX-License-Identifier: 0BSD
@@ -15,7 +18,7 @@ struct JitStateInfo {
: offsetof_guest_MXCSR(offsetof(JitStateType, guest_MXCSR)) : offsetof_guest_MXCSR(offsetof(JitStateType, guest_MXCSR))
, offsetof_asimd_MXCSR(offsetof(JitStateType, asimd_MXCSR)) , offsetof_asimd_MXCSR(offsetof(JitStateType, asimd_MXCSR))
, offsetof_rsb_ptr(offsetof(JitStateType, rsb_ptr)) , offsetof_rsb_ptr(offsetof(JitStateType, rsb_ptr))
, rsb_ptr_mask(JitStateType::RSBPtrMask) , rsb_ptr_mask(JitStateType::RSB_PTR_MASK)
, offsetof_rsb_location_descriptors(offsetof(JitStateType, rsb_location_descriptors)) , offsetof_rsb_location_descriptors(offsetof(JitStateType, rsb_location_descriptors))
, offsetof_rsb_codeptrs(offsetof(JitStateType, rsb_codeptrs)) , offsetof_rsb_codeptrs(offsetof(JitStateType, rsb_codeptrs))
, offsetof_cpsr_nzcv(offsetof(JitStateType, cpsr_nzcv)) , offsetof_cpsr_nzcv(offsetof(JitStateType, cpsr_nzcv))
+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-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,6 +6,7 @@
#include "hid_core/hidbus/starlink.h" #include "hid_core/hidbus/starlink.h"
namespace Service::HID { namespace Service::HID {
constexpr u8 DEVICE_ID = 0x28;
Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_) Starlink::Starlink(Core::System& system_, KernelHelpers::ServiceContext& service_context_)
: HidbusBase(system_, service_context_) {} : HidbusBase(system_, service_context_) {}
@@ -37,7 +35,7 @@ void Starlink::OnUpdate() {
} }
u8 Starlink::GetDeviceId() const { u8 Starlink::GetDeviceId() const {
return 0x28; return DEVICE_ID;
} }
u64 Starlink::GetReply(std::span<u8> out_data) const { 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-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,6 +6,7 @@
#include "hid_core/hidbus/stubbed.h" #include "hid_core/hidbus/stubbed.h"
namespace Service::HID { namespace Service::HID {
constexpr u8 DEVICE_ID = 0xFF;
HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_) HidbusStubbed::HidbusStubbed(Core::System& system_, KernelHelpers::ServiceContext& service_context_)
: HidbusBase(system_, service_context_) {} : HidbusBase(system_, service_context_) {}
@@ -37,7 +35,7 @@ void HidbusStubbed::OnUpdate() {
} }
u8 HidbusStubbed::GetDeviceId() const { u8 HidbusStubbed::GetDeviceId() const {
return 0xFF; return DEVICE_ID;
} }
u64 HidbusStubbed::GetReply(std::span<u8> out_data) const { 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-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later // SPDX-License-Identifier: GPL-3.0-or-later
@@ -11,6 +8,9 @@
#include "hid_core/irsensor/moment_processor.h" #include "hid_core/irsensor/moment_processor.h"
namespace Service::IRS { 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, MomentProcessor::MomentProcessor(Core::System& system_, Core::IrSensor::DeviceFormat& device_format,
std::size_t npad_index) 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 { 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 0;
}
return data[(y * ImageWidth) + x]; return data[(y * ImageWidth) + x];
} }
@@ -92,12 +92,9 @@ MomentProcessor::MomentStatistic MomentProcessor::GetStatistic(const std::vector
std::size_t width, std::size_t width,
std::size_t height) const { std::size_t height) const {
// The actual implementation is always 320x240 // The actual implementation is always 320x240
constexpr std::size_t RealWidth = 320; static constexpr std::size_t RealWidth = 320;
constexpr std::size_t RealHeight = 240; static constexpr std::size_t RealHeight = 240;
constexpr std::size_t Threshold = 30; static constexpr std::size_t Threshold = 30;
constexpr std::size_t ImageWidth = 40;
constexpr std::size_t ImageHeight = 30;
MomentStatistic statistic{}; MomentStatistic statistic{};
std::size_t active_points{}; std::size_t active_points{};
@@ -146,7 +143,7 @@ void MomentProcessor::SetConfig(Core::IrSensor::PackedMomentProcessorConfig conf
static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess); static_cast<Core::IrSensor::MomentProcessorPreprocess>(config.preprocess);
current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold; current_config.preprocess_intensity_threshold = config.preprocess_intensity_threshold;
npad_device->SetCameraFormat(Core::IrSensor::ImageTransferProcessorFormat::Size40x30); npad_device->SetCameraFormat(format);
} }
} // namespace Service::IRS } // 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-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -10,14 +7,14 @@
#include "input_common/drivers/camera.h" #include "input_common/drivers/camera.h"
namespace InputCommon { namespace InputCommon {
constexpr PadIdentifier camera_identifier = { constexpr PadIdentifier identifier = {
.guid = Common::UUID{}, .guid = Common::UUID{},
.port = 0, .port = 0,
.pad = 0, .pad = 0,
}; };
Camera::Camera(std::string input_engine_) : InputEngine(std::move(input_engine_)) { 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) { 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 { 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 mouse_axis_y = 1;
constexpr int wheel_axis_x = 2; constexpr int wheel_axis_x = 2;
constexpr int wheel_axis_y = 3; constexpr int wheel_axis_y = 3;
constexpr PadIdentifier mouse_identifier = { constexpr PadIdentifier identifier = {
.guid = Common::UUID{}, .guid = Common::UUID{},
.port = 0, .port = 0,
.pad = 0, .pad = 0,
@@ -51,16 +51,16 @@ constexpr PadIdentifier touch_identifier = {
}; };
Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) { Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(mouse_identifier); PreSetController(identifier);
PreSetController(real_mouse_identifier); PreSetController(real_mouse_identifier);
PreSetController(touch_identifier); PreSetController(touch_identifier);
PreSetController(motion_identifier); PreSetController(motion_identifier);
// Initialize all mouse axis // Initialize all mouse axis
PreSetAxis(mouse_identifier, mouse_axis_x); PreSetAxis(identifier, mouse_axis_x);
PreSetAxis(mouse_identifier, mouse_axis_y); PreSetAxis(identifier, mouse_axis_y);
PreSetAxis(mouse_identifier, wheel_axis_x); PreSetAxis(identifier, wheel_axis_x);
PreSetAxis(mouse_identifier, wheel_axis_y); PreSetAxis(identifier, wheel_axis_y);
PreSetAxis(real_mouse_identifier, mouse_axis_x); PreSetAxis(real_mouse_identifier, mouse_axis_x);
PreSetAxis(real_mouse_identifier, mouse_axis_y); PreSetAxis(real_mouse_identifier, mouse_axis_y);
PreSetAxis(touch_identifier, mouse_axis_x); PreSetAxis(touch_identifier, mouse_axis_x);
@@ -88,8 +88,8 @@ void Mouse::UpdateStickInput() {
last_mouse_change *= maximum_stick_range; last_mouse_change *= maximum_stick_range;
} }
SetAxis(mouse_identifier, mouse_axis_x, last_mouse_change.x); SetAxis(identifier, mouse_axis_x, last_mouse_change.x);
SetAxis(mouse_identifier, mouse_axis_y, -last_mouse_change.y); SetAxis(identifier, mouse_axis_y, -last_mouse_change.y);
// Decay input over time // Decay input over time
const float clamped_length = (std::min)(1.0f, length); 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; Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity;
const float y_sensitivity = const float y_sensitivity =
Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_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(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_y, static_cast<float>(-mouse_move.y) * y_sensitivity);
last_motion_change = { last_motion_change = {
static_cast<float>(-mouse_move.y) * x_sensitivity, 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) { 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 // Set initial analog parameters
mouse_origin = {x, y}; mouse_origin = {x, y};
@@ -211,13 +211,13 @@ void Mouse::PressTouchButton(f32 touch_x, f32 touch_y, MouseButton button) {
} }
void Mouse::ReleaseButton(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(real_mouse_identifier, static_cast<int>(button), false);
SetButton(touch_identifier, static_cast<int>(button), false); SetButton(touch_identifier, static_cast<int>(button), false);
if (!IsMousePanningEnabled()) { if (!IsMousePanningEnabled()) {
SetAxis(mouse_identifier, mouse_axis_x, 0); SetAxis(identifier, mouse_axis_x, 0);
SetAxis(mouse_identifier, mouse_axis_y, 0); SetAxis(identifier, mouse_axis_y, 0);
} }
last_motion_change.x = 0; last_motion_change.x = 0;
@@ -230,8 +230,8 @@ void Mouse::MouseWheelChange(int x, int y) {
wheel_position.x += x; wheel_position.x += x;
wheel_position.y += y; wheel_position.y += y;
last_motion_change.z += static_cast<f32>(y); last_motion_change.z += static_cast<f32>(y);
SetAxis(mouse_identifier, wheel_axis_x, static_cast<f32>(wheel_position.x)); SetAxis(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_y, static_cast<f32>(wheel_position.y));
} }
void Mouse::ReleaseAllButtons() { 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-FileCopyrightText: Copyright 2021 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -9,14 +6,14 @@
namespace InputCommon { namespace InputCommon {
constexpr PadIdentifier touch_screen_identifier = { constexpr PadIdentifier identifier = {
.guid = Common::UUID{}, .guid = Common::UUID{},
.port = 0, .port = 0,
.pad = 0, .pad = 0,
}; };
TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) { TouchScreen::TouchScreen(std::string input_engine_) : InputEngine(std::move(input_engine_)) {
PreSetController(touch_screen_identifier); PreSetController(identifier);
ReleaseAllTouch(); ReleaseAllTouch();
} }
@@ -29,9 +26,9 @@ void TouchScreen::TouchMoved(float x, float y, std::size_t finger_id) {
} }
const auto i = index.value(); const auto i = index.value();
fingers[i].is_active = true; fingers[i].is_active = true;
SetButton(touch_screen_identifier, static_cast<int>(i), true); SetButton(identifier, static_cast<int>(i), true);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2), x); SetAxis(identifier, static_cast<int>(i * 2), x);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2 + 1), y); SetAxis(identifier, static_cast<int>(i * 2 + 1), y);
} }
void TouchScreen::TouchPressed(float x, float y, std::size_t finger_id) { 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(); const auto i = index.value();
fingers[i].is_enabled = false; fingers[i].is_enabled = false;
SetButton(touch_screen_identifier, static_cast<int>(i), false); SetButton(identifier, static_cast<int>(i), false);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2), 0.0f); SetAxis(identifier, static_cast<int>(i * 2), 0.0f);
SetAxis(touch_screen_identifier, static_cast<int>(i * 2 + 1), 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 { 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( 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::function<void(u16, u16, u16, u16)> data_callback) {
std::thread([=, this] { std::thread([=, this] {
@@ -609,13 +609,13 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
u16 max_x{}; u16 max_x{};
u16 max_y{}; u16 max_y{};
auto current_status = CalibrationStatus::Initialized; Status current_status{Status::Initialized};
SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, [&](Response::PadData data) { SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {}, [&](Response::PadData data) {
constexpr u16 CALIBRATION_THRESHOLD = 100; constexpr u16 CALIBRATION_THRESHOLD = 100;
if (current_status == CalibrationStatus::Initialized) { if (current_status == Status::Initialized) {
// Receiving data means the communication is ready now // Receiving data means the communication is ready now
current_status = CalibrationStatus::Ready; current_status = Status::Ready;
status_callback(current_status); status_callback(current_status);
} }
if (data.touch[0].is_active == 0) { 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); 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_x = (std::min)(min_x, u16(data.touch[0].x));
min_y = (std::min)(min_y, u16(data.touch[0].y)); 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) // First touch - min data (min_x/min_y)
current_status = CalibrationStatus::Stage1Completed; current_status = Status::Stage1Completed;
status_callback(current_status); status_callback(current_status);
} }
if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD && if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD &&
@@ -635,7 +635,7 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
// configuration // configuration
max_x = data.touch[0].x; max_x = data.touch[0].x;
max_y = data.touch[0].y; max_y = data.touch[0].y;
current_status = CalibrationStatus::Completed; current_status = Status::Completed;
data_callback(min_x, min_y, max_x, max_y); data_callback(min_x, min_y, max_x, max_y);
status_callback(current_status); 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-FileCopyrightText: 2018 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -166,7 +163,7 @@ private:
/// An async job allowing configuration of the touchpad calibration. /// An async job allowing configuration of the touchpad calibration.
class CalibrationConfigurationJob { class CalibrationConfigurationJob {
public: public:
enum class CalibrationStatus { enum class Status {
Initialized, Initialized,
Ready, Ready,
Stage1Completed, Stage1Completed,
@@ -179,7 +176,7 @@ public:
* @param data_callback Called when calibration data is ready * @param data_callback Called when calibration data is ready
*/ */
explicit CalibrationConfigurationJob(const std::string& host, u16 port, 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); std::function<void(u16, u16, u16, u16)> data_callback);
~CalibrationConfigurationJob(); ~CalibrationConfigurationJob();
void Stop(); void Stop();
+4 -4
View File
@@ -15,7 +15,7 @@
#include "input_common/drivers/virtual_amiibo.h" #include "input_common/drivers/virtual_amiibo.h"
namespace InputCommon { namespace InputCommon {
constexpr PadIdentifier virtual_amiibo_identifier = { constexpr PadIdentifier identifier = {
.guid = Common::UUID{}, .guid = Common::UUID{},
.port = 0, .port = 0,
.pad = 0, .pad = 0,
@@ -228,13 +228,13 @@ VirtualAmiibo::Info VirtualAmiibo::LoadAmiibo(std::span<u8> data) {
status.state = Common::Input::NfcState::NewAmiibo, status.state = Common::Input::NfcState::NewAmiibo,
memcpy(nfc_data.data(), data.data(), data.size_bytes()); memcpy(nfc_data.data(), data.data(), data.size_bytes());
memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length); memcpy(status.uuid.data(), nfc_data.data(), status.uuid_length);
SetNfc(virtual_amiibo_identifier, status); SetNfc(identifier, status);
return Info::Success; return Info::Success;
} }
VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() { VirtualAmiibo::Info VirtualAmiibo::ReloadAmiibo() {
if (state == State::TagNearby) { if (state == State::TagNearby) {
SetNfc(virtual_amiibo_identifier, status); SetNfc(identifier, status);
return Info::Success; return Info::Success;
} }
@@ -248,7 +248,7 @@ VirtualAmiibo::Info VirtualAmiibo::CloseAmiibo() {
state = State::WaitingForAmiibo; state = State::WaitingForAmiibo;
status.state = Common::Input::NfcState::AmiiboRemoved; status.state = Common::Input::NfcState::AmiiboRemoved;
SetNfc(virtual_amiibo_identifier, status); SetNfc(identifier, status);
status.tag_type = 0; status.tag_type = 0;
return Info::Success; 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-FileCopyrightText: Copyright 2017 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@@ -8,7 +5,6 @@
#include <array> #include <array>
#include <vector> #include <vector>
#include <string>
#include "common/common_types.h" #include "common/common_types.h"
namespace Network { namespace Network {
@@ -122,21 +118,26 @@ private:
template <typename T> template <typename T>
Packet& Packet::Read(std::vector<T>& out_data) { Packet& Packet::Read(std::vector<T>& out_data) {
// First extract the size
u32 size = 0; u32 size = 0;
Read(size); Read(size);
out_data.resize(size); out_data.resize(size);
for (auto& elem : out_data) { // Then extract the data
Read(elem); for (std::size_t i = 0; i < out_data.size(); ++i) {
T character;
Read(character);
out_data[i] = character;
} }
return *this; return *this;
} }
template <typename T, std::size_t S> template <typename T, std::size_t S>
Packet& Packet::Read(std::array<T, S>& out_data) { Packet& Packet::Read(std::array<T, S>& out_data) {
for (auto& elem : out_data) { for (std::size_t i = 0; i < out_data.size(); ++i) {
Read(elem); T character;
Read(character);
out_data[i] = character;
} }
return *this; return *this;
} }

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