mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-30 02:16:06 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| aa0878b636 | |||
| c0a85d0e53 |
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
+4
-1
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -24,6 +27,6 @@ object SettingsFile {
|
|||||||
|
|
||||||
fun loadCustomConfig(game: Game) {
|
fun loadCustomConfig(game: Game) {
|
||||||
val fileName = FileUtil.getFilename(Uri.parse(game.path))
|
val fileName = FileUtil.getFilename(Uri.parse(game.path))
|
||||||
NativeConfig.initializePerGameConfig(game.programId, fileName)
|
NativeConfig.initializePerGameConfig(game.applicationId, fileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -189,7 +189,7 @@ class AddonsFragment : Fragment() {
|
|||||||
fragmentManager = parentFragmentManager,
|
fragmentManager = parentFragmentManager,
|
||||||
addonViewModel = addonViewModel,
|
addonViewModel = addonViewModel,
|
||||||
documents = documents,
|
documents = documents,
|
||||||
programId = args.game.programId
|
programId = args.game.applicationId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -347,7 +347,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (GpuDriverHelper.isAdrenoGpu()) {
|
if (GpuDriverHelper.isAdrenoGpu()) {
|
||||||
val programIdHex = game!!.programIdHex
|
val programIdHex = game!!.applicationIdHex
|
||||||
if (NativeFreedrenoConfig.loadPerGameConfigWithGlobalFallback(programIdHex)) {
|
if (NativeFreedrenoConfig.loadPerGameConfigWithGlobalFallback(programIdHex)) {
|
||||||
Log.info("[EmulationFragment] Loaded per-game Freedreno config for $programIdHex")
|
Log.info("[EmulationFragment] Loaded per-game Freedreno config for $programIdHex")
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+2
-2
@@ -59,7 +59,7 @@ class FreedrenoSettingsFragment : Fragment() {
|
|||||||
NativeFreedrenoConfig.initializeFreedrenoConfig()
|
NativeFreedrenoConfig.initializeFreedrenoConfig()
|
||||||
|
|
||||||
if (isPerGameConfig) {
|
if (isPerGameConfig) {
|
||||||
NativeFreedrenoConfig.loadPerGameConfig(game!!.programIdHex)
|
NativeFreedrenoConfig.loadPerGameConfig(game!!.applicationIdHex)
|
||||||
} else {
|
} else {
|
||||||
NativeFreedrenoConfig.reloadFreedrenoConfig()
|
NativeFreedrenoConfig.reloadFreedrenoConfig()
|
||||||
}
|
}
|
||||||
@@ -157,7 +157,7 @@ class FreedrenoSettingsFragment : Fragment() {
|
|||||||
|
|
||||||
binding.buttonSave.setOnClickListener {
|
binding.buttonSave.setOnClickListener {
|
||||||
if (isPerGameConfig) {
|
if (isPerGameConfig) {
|
||||||
NativeFreedrenoConfig.savePerGameConfig(game!!.programIdHex)
|
NativeFreedrenoConfig.savePerGameConfig(game!!.applicationIdHex)
|
||||||
showSnackbar(getString(R.string.freedreno_per_game_saved))
|
showSnackbar(getString(R.string.freedreno_per_game_saved))
|
||||||
} else {
|
} else {
|
||||||
NativeFreedrenoConfig.saveFreedrenoConfig()
|
NativeFreedrenoConfig.saveFreedrenoConfig()
|
||||||
|
|||||||
@@ -455,7 +455,7 @@ class GamePropertiesFragment : Fragment() {
|
|||||||
|
|
||||||
val shaderCacheDir = File(
|
val shaderCacheDir = File(
|
||||||
DirectoryInitialization.userDirectory +
|
DirectoryInitialization.userDirectory +
|
||||||
"/cache/shader/" + args.game.settingsName.lowercase()
|
"/cache/shader/" + args.game.shaderCacheName.lowercase()
|
||||||
)
|
)
|
||||||
if (shaderCacheDir.exists()) {
|
if (shaderCacheDir.exists()) {
|
||||||
add(
|
add(
|
||||||
@@ -600,7 +600,7 @@ class GamePropertiesFragment : Fragment() {
|
|||||||
val files = cacheSaveDir.listFiles()
|
val files = cacheSaveDir.listFiles()
|
||||||
var savesFolderFile: File? = null
|
var savesFolderFile: File? = null
|
||||||
if (files != null) {
|
if (files != null) {
|
||||||
val savesFolderName = args.game.programIdHex
|
val savesFolderName = args.game.applicationIdHex
|
||||||
for (file in files) {
|
for (file in files) {
|
||||||
if (file.isDirectory && file.name == savesFolderName) {
|
if (file.isDirectory && file.name == savesFolderName) {
|
||||||
savesFolderFile = file
|
savesFolderFile = file
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ class InstallableFragment : Fragment() {
|
|||||||
fragmentManager = parentFragmentManager,
|
fragmentManager = parentFragmentManager,
|
||||||
addonViewModel = addonViewModel,
|
addonViewModel = addonViewModel,
|
||||||
documents = documents,
|
documents = documents,
|
||||||
programId = addonViewModel.game?.programId
|
programId = addonViewModel.game?.applicationId
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -142,10 +142,11 @@ class AddonViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun onDeleteAddon(patch: Patch) {
|
fun onDeleteAddon(patch: Patch) {
|
||||||
|
val currentGame = game ?: return
|
||||||
when (PatchType.from(patch.type)) {
|
when (PatchType.from(patch.type)) {
|
||||||
PatchType.Update -> NativeLibrary.removeUpdate(patch.programId)
|
PatchType.Update -> NativeLibrary.removeUpdate(currentGame.programId)
|
||||||
PatchType.DLC -> NativeLibrary.removeDLC(patch.programId)
|
PatchType.DLC -> NativeLibrary.removeDLC(currentGame.applicationId)
|
||||||
PatchType.Mod -> NativeLibrary.removeMod(patch.programId, patch.name)
|
PatchType.Mod -> NativeLibrary.removeMod(currentGame.programId, patch.name)
|
||||||
}
|
}
|
||||||
refreshAddons(force = true)
|
refreshAddons(force = true)
|
||||||
}
|
}
|
||||||
@@ -165,7 +166,7 @@ class AddonViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NativeConfig.setDisabledAddons(
|
NativeConfig.setDisabledAddons(
|
||||||
currentGame.programId,
|
currentGame.applicationId,
|
||||||
currentList.mapNotNull {
|
currentList.mapNotNull {
|
||||||
if (it.enabled) {
|
if (it.enabled) {
|
||||||
null
|
null
|
||||||
@@ -199,6 +200,6 @@ class AddonViewModel : ViewModel() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun gameKey(game: Game): String {
|
private fun gameKey(game: Game): String {
|
||||||
return "${game.programId}|${game.path}"
|
return "${game.applicationId}|${game.path}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ class DriverViewModel : ViewModel() {
|
|||||||
?: return@withContext
|
?: return@withContext
|
||||||
val shaderDir = File(
|
val shaderDir = File(
|
||||||
externalFilesDir.absolutePath +
|
externalFilesDir.absolutePath +
|
||||||
"/shader/" + game.settingsName.lowercase()
|
"/shader/" + game.shaderCacheName.lowercase()
|
||||||
)
|
)
|
||||||
if (shaderDir.exists()) {
|
if (shaderDir.exists()) {
|
||||||
shaderDir.deleteRecursively()
|
shaderDir.deleteRecursively()
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
@@ -35,19 +35,26 @@ class Game(
|
|||||||
val keyAddedToLibraryTime get() = "${path}_AddedToLibraryTime"
|
val keyAddedToLibraryTime get() = "${path}_AddedToLibraryTime"
|
||||||
val keyLastPlayedTime get() = "${path}_LastPlayed"
|
val keyLastPlayedTime get() = "${path}_LastPlayed"
|
||||||
|
|
||||||
|
private val programIdLong: Long
|
||||||
|
get() = programId.toLongOrNull() ?: 0L
|
||||||
|
|
||||||
|
private val applicationIdLong: Long
|
||||||
|
get() = programIdLong and -8192L
|
||||||
|
|
||||||
|
val applicationId: String
|
||||||
|
get() = applicationIdLong.toString()
|
||||||
|
|
||||||
val settingsName: String
|
val settingsName: String
|
||||||
get() {
|
get() {
|
||||||
val programIdLong = programId.toLong()
|
return if (applicationIdLong == 0L) {
|
||||||
return if (programIdLong == 0L) {
|
|
||||||
FileUtil.getFilename(Uri.parse(path))
|
FileUtil.getFilename(Uri.parse(path))
|
||||||
} else {
|
} else {
|
||||||
"0" + programIdLong.toString(16).uppercase()
|
"0" + applicationIdLong.toString(16).uppercase()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val programIdHex: String
|
val programIdHex: String
|
||||||
get() {
|
get() {
|
||||||
val programIdLong = programId.toLong()
|
|
||||||
return if (programIdLong == 0L) {
|
return if (programIdLong == 0L) {
|
||||||
"0"
|
"0"
|
||||||
} else {
|
} else {
|
||||||
@@ -55,16 +62,32 @@ class Game(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val shaderCacheName: String
|
||||||
|
get() = if (programIdLong == 0L) {
|
||||||
|
FileUtil.getFilename(Uri.parse(path))
|
||||||
|
} else {
|
||||||
|
"0" + programIdLong.toString(16).uppercase()
|
||||||
|
}
|
||||||
|
|
||||||
|
val applicationIdHex: String
|
||||||
|
get() {
|
||||||
|
return if (applicationIdLong == 0L) {
|
||||||
|
"0"
|
||||||
|
} else {
|
||||||
|
"0" + applicationIdLong.toString(16).uppercase()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
val saveZipName: String
|
val saveZipName: String
|
||||||
get() = "$title ${YuzuApplication.appContext.getString(R.string.save_data).lowercase()} - ${
|
get() = "$title ${YuzuApplication.appContext.getString(R.string.save_data).lowercase()} - ${
|
||||||
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
|
LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"))
|
||||||
}.zip"
|
}.zip"
|
||||||
|
|
||||||
val saveDir: String
|
val saveDir: String
|
||||||
get() = NativeConfig.getSaveDir() + NativeLibrary.getSavePath(programId)
|
get() = NativeConfig.getSaveDir() + NativeLibrary.getSavePath(applicationId)
|
||||||
|
|
||||||
val addonDir: String
|
val addonDir: String
|
||||||
get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/"
|
get() = DirectoryInitialization.userDirectory + "/load/" + applicationIdHex + "/"
|
||||||
|
|
||||||
val launchIntent: Intent
|
val launchIntent: Intent
|
||||||
get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
|
get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||||
@@ -65,7 +65,7 @@ object CustomSettingsHandler {
|
|||||||
// Initialize per-game config
|
// Initialize per-game config
|
||||||
try {
|
try {
|
||||||
val fileName = FileUtil.getFilename(Uri.parse(game.path))
|
val fileName = FileUtil.getFilename(Uri.parse(game.path))
|
||||||
NativeConfig.initializePerGameConfig(game.programId, fileName)
|
NativeConfig.initializePerGameConfig(game.applicationId, fileName)
|
||||||
Log.info("[CustomSettingsHandler] Successfully applied custom settings")
|
Log.info("[CustomSettingsHandler] Successfully applied custom settings")
|
||||||
return game
|
return game
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
@@ -333,20 +333,20 @@ object CustomSettingsHandler {
|
|||||||
*/
|
*/
|
||||||
fun findGameByTitleId(titleId: String, context: Context): Game? {
|
fun findGameByTitleId(titleId: String, context: Context): Game? {
|
||||||
Log.info("[CustomSettingsHandler] Searching for game with title ID: $titleId")
|
Log.info("[CustomSettingsHandler] Searching for game with title ID: $titleId")
|
||||||
// Convert hex title ID to decimal for comparison with programId
|
// Convert the program ID to the application ID used by per-game settings.
|
||||||
val programIdDecimal = try {
|
val applicationIdLong = try {
|
||||||
titleId.toLong(16).toString()
|
titleId.toLong(16) and -8192L
|
||||||
} catch (e: NumberFormatException) {
|
} catch (e: NumberFormatException) {
|
||||||
Log.error("[CustomSettingsHandler] Invalid title ID format: $titleId")
|
Log.error("[CustomSettingsHandler] Invalid title ID format: $titleId")
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
val applicationIdDecimal = applicationIdLong.toString()
|
||||||
|
|
||||||
// Expected hex format with "0" prefix
|
// Expected hex format with "0" prefix
|
||||||
val expectedHex = "0${titleId.uppercase()}"
|
val expectedHex = "0${applicationIdLong.toString(16).uppercase()}"
|
||||||
// First check cached games for fast lookup
|
// First check cached games for fast lookup
|
||||||
GameHelper.cachedGameList.find { game ->
|
GameHelper.cachedGameList.find { game ->
|
||||||
game.programId == programIdDecimal ||
|
game.applicationId == applicationIdDecimal || game.applicationIdHex.equals(expectedHex, ignoreCase = true)
|
||||||
game.programIdHex.equals(expectedHex, ignoreCase = true)
|
|
||||||
}?.let { foundGame ->
|
}?.let { foundGame ->
|
||||||
Log.info("[CustomSettingsHandler] Found game in cache: ${foundGame.title}")
|
Log.info("[CustomSettingsHandler] Found game in cache: ${foundGame.title}")
|
||||||
return foundGame
|
return foundGame
|
||||||
@@ -355,8 +355,7 @@ object CustomSettingsHandler {
|
|||||||
Log.info("[CustomSettingsHandler] Game not in cache, scanning full library...")
|
Log.info("[CustomSettingsHandler] Game not in cache, scanning full library...")
|
||||||
val allGames = GameHelper.getGames()
|
val allGames = GameHelper.getGames()
|
||||||
val foundGame = allGames.find { game ->
|
val foundGame = allGames.find { game ->
|
||||||
game.programId == programIdDecimal ||
|
game.applicationId == applicationIdDecimal || game.applicationIdHex.equals(expectedHex, ignoreCase = true)
|
||||||
game.programIdHex.equals(expectedHex, ignoreCase = true)
|
|
||||||
}
|
}
|
||||||
if (foundGame != null) {
|
if (foundGame != null) {
|
||||||
Log.info("[CustomSettingsHandler] Found game: ${foundGame.title} at ${foundGame.path}")
|
Log.info("[CustomSettingsHandler] Found game: ${foundGame.title} at ${foundGame.path}")
|
||||||
|
|||||||
@@ -170,12 +170,12 @@ object GameHelper {
|
|||||||
val game = getGame(it.uri, true, false)
|
val game = getGame(it.uri, true, false)
|
||||||
if (game != null) {
|
if (game != null) {
|
||||||
games.add(game)
|
games.add(game)
|
||||||
if (game.programId != "0") {
|
if (game.applicationId != "0") {
|
||||||
gamesByProgramId[game.programId] = game
|
gamesByProgramId[game.applicationId] = game
|
||||||
}
|
}
|
||||||
} else if (mountedContainer) {
|
} else if (mountedContainer) {
|
||||||
GameMetadata.getProgramId(filePath).toLongOrNull()?.let { programId ->
|
GameMetadata.getProgramId(filePath).toLongOrNull()?.let { programId ->
|
||||||
gamesByProgramId[(programId and 0x800L.inv()).toString()]
|
gamesByProgramId[(programId and -8192L).toString()]
|
||||||
}?.let { existingGame ->
|
}?.let { existingGame ->
|
||||||
NativeLibrary.getPatchesForFile(existingGame.path, existingGame.programId)
|
NativeLibrary.getPatchesForFile(existingGame.path, existingGame.programId)
|
||||||
existingGame.version = GameMetadata.getVersion(
|
existingGame.version = GameMetadata.getVersion(
|
||||||
|
|||||||
@@ -788,7 +788,7 @@ int Java_org_yuzu_yuzu_1emu_NativeLibrary_installFileToNand(JNIEnv* env, jobject
|
|||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj,
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* env, jobject jobj,
|
||||||
jstring jprogramId,
|
jstring jprogramId,
|
||||||
jstring jupdatePath) {
|
jstring jupdatePath) {
|
||||||
u64 program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const u64 program_id = FileSys::GetBaseTitleID(EmulationSession::GetProgramId(env, jprogramId));
|
||||||
std::string updatePath = Common::Android::GetJString(env, jupdatePath);
|
std::string updatePath = Common::Android::GetJString(env, jupdatePath);
|
||||||
std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>(
|
std::shared_ptr<FileSys::NSP> nsp = std::make_shared<FileSys::NSP>(
|
||||||
EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
|
EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
|
||||||
@@ -796,7 +796,7 @@ jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_doesUpdateMatchProgram(JNIEnv* en
|
|||||||
for (const auto& item : nsp->GetNCAs()) {
|
for (const auto& item : nsp->GetNCAs()) {
|
||||||
for (const auto& nca_details : item.second) {
|
for (const auto& nca_details : item.second) {
|
||||||
if (nca_details.second->GetName().ends_with(".cnmt.nca")) {
|
if (nca_details.second->GetName().ends_with(".cnmt.nca")) {
|
||||||
auto update_id = nca_details.second->GetTitleId() & ~0xFFFULL;
|
const auto update_id = FileSys::GetBaseTitleID(nca_details.second->GetTitleId());
|
||||||
if (update_id == program_id) {
|
if (update_id == program_id) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -1491,7 +1491,7 @@ jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_firmwareVersion(JNIEnv* env, jclas
|
|||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_gameRequiresFirmware(JNIEnv* env, jclass clazz, jstring jprogramId) {
|
jboolean Java_org_yuzu_yuzu_1emu_NativeLibrary_gameRequiresFirmware(JNIEnv* env, jclass clazz, jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = FileSys::GetBaseTitleID(EmulationSession::GetProgramId(env, jprogramId));
|
||||||
|
|
||||||
return FirmwareManager::GameRequiresFirmware(program_id);
|
return FirmwareManager::GameRequiresFirmware(program_id);
|
||||||
}
|
}
|
||||||
@@ -1575,20 +1575,21 @@ jobjectArray Java_org_yuzu_yuzu_1emu_NativeLibrary_getPatchesForFile(JNIEnv* env
|
|||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeUpdate(JNIEnv* env, jobject jobj,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeUpdate(JNIEnv* env, jobject jobj,
|
||||||
jstring jprogramId) {
|
jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
||||||
ContentManager::RemoveUpdate(EmulationSession::GetInstance().System().GetFileSystemController(),
|
ContentManager::RemoveUpdate(EmulationSession::GetInstance().System().GetFileSystemController(),
|
||||||
program_id);
|
program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeDLC(JNIEnv* env, jobject jobj,
|
||||||
jstring jprogramId) {
|
jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = FileSys::GetBaseTitleID(
|
||||||
|
EmulationSession::GetProgramId(env, jprogramId));
|
||||||
ContentManager::RemoveAllDLC(EmulationSession::GetInstance().System(), program_id);
|
ContentManager::RemoveAllDLC(EmulationSession::GetInstance().System(), program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId,
|
void Java_org_yuzu_yuzu_1emu_NativeLibrary_removeMod(JNIEnv* env, jobject jobj, jstring jprogramId,
|
||||||
jstring jname) {
|
jstring jname) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
||||||
ContentManager::RemoveMod(EmulationSession::GetInstance().System().GetFileSystemController(),
|
ContentManager::RemoveMod(EmulationSession::GetInstance().System().GetFileSystemController(),
|
||||||
program_id, Common::Android::GetJString(env, jname));
|
program_id, Common::Android::GetJString(env, jname));
|
||||||
}
|
}
|
||||||
@@ -1635,7 +1636,7 @@ jint Java_org_yuzu_yuzu_1emu_NativeLibrary_verifyGameContents(JNIEnv* env, jobje
|
|||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj,
|
jstring Java_org_yuzu_yuzu_1emu_NativeLibrary_getSavePath(JNIEnv* env, jobject jobj,
|
||||||
jstring jprogramId) {
|
jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = FileSys::GetBaseTitleID(EmulationSession::GetProgramId(env, jprogramId));
|
||||||
if (program_id == 0) {
|
if (program_id == 0) {
|
||||||
return Common::Android::ToJString(env, "");
|
return Common::Android::ToJString(env, "");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "frontend_common/config.h"
|
#include "frontend_common/config.h"
|
||||||
#include "frontend_common/settings_generator.h"
|
#include "frontend_common/settings_generator.h"
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
@@ -56,7 +57,7 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_saveGlobalConfig(JNIEnv* env, jo
|
|||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializePerGameConfig(JNIEnv* env, jobject obj,
|
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_initializePerGameConfig(JNIEnv* env, jobject obj,
|
||||||
jstring jprogramId,
|
jstring jprogramId,
|
||||||
jstring jfileName) {
|
jstring jfileName) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = FileSys::GetBaseTitleID(EmulationSession::GetProgramId(env, jprogramId));
|
||||||
auto file_name = Common::Android::GetJString(env, jfileName);
|
auto file_name = Common::Android::GetJString(env, jfileName);
|
||||||
const auto config_file_name = program_id == 0 ? file_name : fmt::format("{:016X}", program_id);
|
const auto config_file_name = program_id == 0 ? file_name : fmt::format("{:016X}", program_id);
|
||||||
per_game_config =
|
per_game_config =
|
||||||
@@ -322,7 +323,7 @@ void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_addGameDir(JNIEnv* env, jobject
|
|||||||
|
|
||||||
jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getDisabledAddons(JNIEnv* env, jobject obj,
|
jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getDisabledAddons(JNIEnv* env, jobject obj,
|
||||||
jstring jprogramId) {
|
jstring jprogramId) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = FileSys::GetBaseTitleID(EmulationSession::GetProgramId(env, jprogramId));
|
||||||
auto& disabledAddons = Settings::values.disabled_addons[program_id];
|
auto& disabledAddons = Settings::values.disabled_addons[program_id];
|
||||||
jobjectArray jdisabledAddonsArray =
|
jobjectArray jdisabledAddonsArray =
|
||||||
env->NewObjectArray(disabledAddons.size(), Common::Android::GetStringClass(),
|
env->NewObjectArray(disabledAddons.size(), Common::Android::GetStringClass(),
|
||||||
@@ -337,7 +338,7 @@ jobjectArray Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getDisabledAddons(JNIEnv
|
|||||||
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setDisabledAddons(JNIEnv* env, jobject obj,
|
void Java_org_yuzu_yuzu_1emu_utils_NativeConfig_setDisabledAddons(JNIEnv* env, jobject obj,
|
||||||
jstring jprogramId,
|
jstring jprogramId,
|
||||||
jobjectArray jdisabledAddons) {
|
jobjectArray jdisabledAddons) {
|
||||||
auto program_id = EmulationSession::GetProgramId(env, jprogramId);
|
const auto program_id = FileSys::GetBaseTitleID(EmulationSession::GetProgramId(env, jprogramId));
|
||||||
Settings::values.disabled_addons[program_id].clear();
|
Settings::values.disabled_addons[program_id].clear();
|
||||||
std::vector<std::string> disabled_addons;
|
std::vector<std::string> disabled_addons;
|
||||||
const int size = env->GetArrayLength(jdisabledAddons);
|
const int size = env->GetArrayLength(jdisabledAddons);
|
||||||
|
|||||||
@@ -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,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-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|||||||
@@ -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_)} {}
|
||||||
|
|||||||
@@ -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_)} {}
|
||||||
|
|||||||
@@ -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,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;
|
||||||
|
|||||||
@@ -16,5 +16,3 @@
|
|||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic pop
|
#pragma GCC diagnostic pop
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#undef INVALID_SOCKET
|
|
||||||
|
|||||||
@@ -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));
|
||||||
|
|||||||
+36
-7
@@ -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"
|
||||||
@@ -16,6 +17,7 @@
|
|||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/arm/exclusive_monitor.h"
|
#include "core/arm/exclusive_monitor.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
|
|
||||||
#include "launch_timestamp_cache.h"
|
#include "launch_timestamp_cache.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
@@ -248,12 +250,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) {
|
||||||
@@ -377,7 +397,7 @@ struct System::Impl {
|
|||||||
LOG_ERROR(Core, "Failed to find program id for ROM");
|
LOG_ERROR(Core, "Failed to find program id for ROM");
|
||||||
}
|
}
|
||||||
|
|
||||||
GameSettings::LoadOverrides(program_id, gpu_core->Renderer());
|
GameSettings::LoadOverrides(FileSys::GetBaseTitleID(program_id), gpu_core->Renderer());
|
||||||
if (auto room_member = Network::GetRoomMember().lock()) {
|
if (auto room_member = Network::GetRoomMember().lock()) {
|
||||||
Network::GameInfo game_info;
|
Network::GameInfo game_info;
|
||||||
game_info.name = name;
|
game_info.name = name;
|
||||||
@@ -505,6 +525,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 +534,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 +597,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
@@ -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.
|
||||||
|
|||||||
@@ -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));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,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,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;
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ std::string GetUpdateVersionStringFromSlot(const ContentProvider* provider, u64
|
|||||||
PatchManager::PatchManager(u64 title_id_,
|
PatchManager::PatchManager(u64 title_id_,
|
||||||
const Service::FileSystem::FileSystemController& fs_controller_,
|
const Service::FileSystem::FileSystemController& fs_controller_,
|
||||||
const ContentProvider& content_provider_)
|
const ContentProvider& content_provider_)
|
||||||
: title_id{title_id_}, fs_controller{fs_controller_}, content_provider{content_provider_} {}
|
: title_id{title_id_}, application_id{GetBaseTitleID(title_id_)}, fs_controller{fs_controller_}, content_provider{content_provider_} {}
|
||||||
|
|
||||||
PatchManager::~PatchManager() = default;
|
PatchManager::~PatchManager() = default;
|
||||||
|
|
||||||
@@ -169,13 +169,41 @@ u64 PatchManager::GetTitleID() const {
|
|||||||
return title_id;
|
return title_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 PatchManager::GetUpdateTitleIDForContent() const {
|
||||||
|
const auto program_update_id = GetUpdateTitleID(title_id);
|
||||||
|
if (program_update_id == GetUpdateTitleID(application_id) || content_provider.HasEntry(program_update_id, ContentRecordType::Program)) {
|
||||||
|
return program_update_id;
|
||||||
|
}
|
||||||
|
return GetUpdateTitleID(application_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VirtualDir> PatchManager::GetModificationLoadRoots() const {
|
||||||
|
std::vector<VirtualDir> roots;
|
||||||
|
roots.push_back(fs_controller.GetModificationLoadRoot(title_id));
|
||||||
|
if (application_id != title_id) {
|
||||||
|
roots.push_back(fs_controller.GetModificationLoadRoot(application_id));
|
||||||
|
}
|
||||||
|
std::erase(roots, nullptr);
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<VirtualDir> PatchManager::GetSDMCModificationLoadRoots() const {
|
||||||
|
std::vector<VirtualDir> roots;
|
||||||
|
roots.push_back(fs_controller.GetSDMCModificationLoadRoot(title_id));
|
||||||
|
if (application_id != title_id) {
|
||||||
|
roots.push_back(fs_controller.GetSDMCModificationLoadRoot(application_id));
|
||||||
|
}
|
||||||
|
std::erase(roots, nullptr);
|
||||||
|
return roots;
|
||||||
|
}
|
||||||
|
|
||||||
VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
||||||
LOG_INFO(Loader, "Patching ExeFS for title_id={:016X}", title_id);
|
LOG_INFO(Loader, "Patching ExeFS for title_id={:016X}", title_id);
|
||||||
|
|
||||||
if (exefs == nullptr)
|
if (exefs == nullptr)
|
||||||
return exefs;
|
return exefs;
|
||||||
|
|
||||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
const auto& disabled = Settings::values.disabled_addons[application_id];
|
||||||
|
|
||||||
bool update_disabled = true;
|
bool update_disabled = true;
|
||||||
std::optional<u32> enabled_version;
|
std::optional<u32> enabled_version;
|
||||||
@@ -183,7 +211,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
|||||||
bool checked_manual = false;
|
bool checked_manual = false;
|
||||||
|
|
||||||
const auto* content_union = static_cast<const ContentProviderUnion*>(&content_provider);
|
const auto* content_union = static_cast<const ContentProviderUnion*>(&content_provider);
|
||||||
const auto update_tid = GetUpdateTitleID(title_id);
|
const auto update_tid = GetUpdateTitleIDForContent();
|
||||||
|
|
||||||
if (content_union) {
|
if (content_union) {
|
||||||
// First, check ExternalContentProvider
|
// First, check ExternalContentProvider
|
||||||
@@ -303,17 +331,21 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// LayeredExeFS
|
// LayeredExeFS
|
||||||
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
const auto load_dirs = GetModificationLoadRoots();
|
||||||
const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
|
const auto sdmc_load_dirs = GetSDMCModificationLoadRoots();
|
||||||
|
|
||||||
std::vector<VirtualDir> patch_dirs = {sdmc_load_dir};
|
std::vector<VirtualDir> patch_dirs;
|
||||||
if (load_dir != nullptr) {
|
for (const auto& sdmc_load_dir : sdmc_load_dirs) {
|
||||||
|
patch_dirs.push_back(sdmc_load_dir);
|
||||||
|
}
|
||||||
|
for (const auto& load_dir : load_dirs) {
|
||||||
const auto load_patch_dirs = load_dir->GetSubdirectories();
|
const auto load_patch_dirs = load_dir->GetSubdirectories();
|
||||||
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
|
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(patch_dirs.begin(), patch_dirs.end(),
|
std::stable_sort(patch_dirs.begin(), patch_dirs.end(), [](const VirtualDir& l, const VirtualDir& r) {
|
||||||
[](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
|
return l->GetName() < r->GetName();
|
||||||
|
});
|
||||||
|
|
||||||
std::vector<VirtualDir> layers;
|
std::vector<VirtualDir> layers;
|
||||||
layers.reserve(patch_dirs.size() + 1);
|
layers.reserve(patch_dirs.size() + 1);
|
||||||
@@ -347,7 +379,7 @@ VirtualDir PatchManager::PatchExeFS(VirtualDir exefs) const {
|
|||||||
|
|
||||||
std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
std::vector<VirtualFile> PatchManager::CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
||||||
const std::string& build_id) const {
|
const std::string& build_id) const {
|
||||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
const auto& disabled = Settings::values.disabled_addons[application_id];
|
||||||
const auto nso_build_id = fmt::format("{:0<64}", build_id);
|
const auto nso_build_id = fmt::format("{:0<64}", build_id);
|
||||||
|
|
||||||
std::vector<VirtualFile> out;
|
std::vector<VirtualFile> out;
|
||||||
@@ -412,15 +444,20 @@ std::vector<u8> PatchManager::PatchNSO(const std::vector<u8>& nso, const std::st
|
|||||||
|
|
||||||
LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id);
|
LOG_INFO(Loader, "Patching NSO for name={}, build_id={}", name, build_id);
|
||||||
|
|
||||||
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
const auto load_dirs = GetModificationLoadRoots();
|
||||||
if (load_dir == nullptr) {
|
if (load_dirs.empty()) {
|
||||||
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
|
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
|
||||||
return nso;
|
return nso;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto patch_dirs = load_dir->GetSubdirectories();
|
std::vector<VirtualDir> patch_dirs;
|
||||||
std::sort(patch_dirs.begin(), patch_dirs.end(),
|
for (const auto& load_dir : load_dirs) {
|
||||||
[](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
|
const auto load_patch_dirs = load_dir->GetSubdirectories();
|
||||||
|
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
|
||||||
|
}
|
||||||
|
std::stable_sort(patch_dirs.begin(), patch_dirs.end(), [](const VirtualDir& l, const VirtualDir& r) {
|
||||||
|
return l->GetName() < r->GetName();
|
||||||
|
});
|
||||||
const auto patches = CollectPatches(patch_dirs, build_id);
|
const auto patches = CollectPatches(patch_dirs, build_id);
|
||||||
|
|
||||||
auto out = nso;
|
auto out = nso;
|
||||||
@@ -455,29 +492,39 @@ bool PatchManager::HasNSOPatch(const BuildID& build_id_, std::string_view name)
|
|||||||
|
|
||||||
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}, name={}", build_id, name);
|
LOG_INFO(Loader, "Querying NSO patch existence for build_id={}, name={}", build_id, name);
|
||||||
|
|
||||||
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
const auto load_dirs = GetModificationLoadRoots();
|
||||||
if (load_dir == nullptr) {
|
if (load_dirs.empty()) {
|
||||||
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
|
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto patch_dirs = load_dir->GetSubdirectories();
|
std::vector<VirtualDir> patch_dirs;
|
||||||
std::sort(patch_dirs.begin(), patch_dirs.end(),
|
for (const auto& load_dir : load_dirs) {
|
||||||
[](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
|
const auto load_patch_dirs = load_dir->GetSubdirectories();
|
||||||
|
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
|
||||||
|
}
|
||||||
|
std::stable_sort(patch_dirs.begin(), patch_dirs.end(), [](const VirtualDir& l, const VirtualDir& r) {
|
||||||
|
return l->GetName() < r->GetName();
|
||||||
|
});
|
||||||
|
|
||||||
return !CollectPatches(patch_dirs, build_id).empty();
|
return !CollectPatches(patch_dirs, build_id).empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(const BuildID& build_id_) const {
|
std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(const BuildID& build_id_) const {
|
||||||
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
const auto load_dirs = GetModificationLoadRoots();
|
||||||
if (load_dir == nullptr) {
|
if (load_dirs.empty()) {
|
||||||
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
|
LOG_ERROR(Loader, "Cannot load mods for invalid title_id={:016X}", title_id);
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
const auto& disabled = Settings::values.disabled_addons[application_id];
|
||||||
auto patch_dirs = load_dir->GetSubdirectories();
|
std::vector<VirtualDir> patch_dirs;
|
||||||
std::sort(patch_dirs.begin(), patch_dirs.end(), [](auto const& l, auto const& r) { return l->GetName() < r->GetName(); });
|
for (const auto& load_dir : load_dirs) {
|
||||||
|
const auto load_patch_dirs = load_dir->GetSubdirectories();
|
||||||
|
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
|
||||||
|
}
|
||||||
|
std::stable_sort(patch_dirs.begin(), patch_dirs.end(),
|
||||||
|
[](auto const& l, auto const& r) { return l->GetName() < r->GetName(); });
|
||||||
|
|
||||||
// <mod dir> / <folder> / cheats / <build id>.txt
|
// <mod dir> / <folder> / cheats / <build id>.txt
|
||||||
std::vector<Core::Memory::CheatEntry> out;
|
std::vector<Core::Memory::CheatEntry> out;
|
||||||
@@ -493,39 +540,52 @@ std::vector<Core::Memory::CheatEntry> PatchManager::CreateCheatList(const BuildI
|
|||||||
}
|
}
|
||||||
// Uncareless user-friendly loading of patches (must start with 'cheat_')
|
// Uncareless user-friendly loading of patches (must start with 'cheat_')
|
||||||
// <mod dir> / <cheat file>.txt
|
// <mod dir> / <cheat file>.txt
|
||||||
for (auto const& f : load_dir->GetFiles()) {
|
for (const auto& load_dir : load_dirs) {
|
||||||
auto const name = f->GetName();
|
for (auto const& f : load_dir->GetFiles()) {
|
||||||
if (name.starts_with("cheat_") && std::find(disabled.cbegin(), disabled.cend(), name) == disabled.cend()) {
|
auto const name = f->GetName();
|
||||||
std::vector<u8> data(f->GetSize());
|
if (name.starts_with("cheat_") && std::find(disabled.cbegin(), disabled.cend(), name) == disabled.cend()) {
|
||||||
if (f->Read(data.data(), data.size()) == data.size()) {
|
std::vector<u8> data(f->GetSize());
|
||||||
const Core::Memory::TextCheatParser parser;
|
if (f->Read(data.data(), data.size()) == data.size()) {
|
||||||
auto const res = parser.Parse(std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
|
const Core::Memory::TextCheatParser parser;
|
||||||
std::copy(res.begin(), res.end(), std::back_inserter(out));
|
auto const res = parser.Parse(std::string_view(reinterpret_cast<const char*>(data.data()), data.size()));
|
||||||
} else {
|
std::copy(res.begin(), res.end(), std::back_inserter(out));
|
||||||
LOG_INFO(Common_Filesystem, "Failed to read cheats file for title_id={:016X}", title_id);
|
} else {
|
||||||
|
LOG_INFO(Common_Filesystem, "Failed to read cheats file for title_id={:016X}", title_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, ContentRecordType type,
|
static void ApplyLayeredFS(VirtualFile& romfs, u64 title_id, u64 application_id, ContentRecordType type,
|
||||||
const Service::FileSystem::FileSystemController& fs_controller) {
|
const Service::FileSystem::FileSystemController& fs_controller) {
|
||||||
const auto load_dir = fs_controller.GetModificationLoadRoot(title_id);
|
std::vector<VirtualDir> load_dirs{fs_controller.GetModificationLoadRoot(title_id)};
|
||||||
const auto sdmc_load_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
|
std::vector<VirtualDir> sdmc_load_dirs{fs_controller.GetSDMCModificationLoadRoot(title_id)};
|
||||||
|
if (application_id != title_id) {
|
||||||
|
load_dirs.push_back(fs_controller.GetModificationLoadRoot(application_id));
|
||||||
|
sdmc_load_dirs.push_back(fs_controller.GetSDMCModificationLoadRoot(application_id));
|
||||||
|
}
|
||||||
|
std::erase(load_dirs, nullptr);
|
||||||
|
std::erase(sdmc_load_dirs, nullptr);
|
||||||
if ((type != ContentRecordType::Program && type != ContentRecordType::Data &&
|
if ((type != ContentRecordType::Program && type != ContentRecordType::Data &&
|
||||||
type != ContentRecordType::HtmlDocument) ||
|
type != ContentRecordType::HtmlDocument) ||
|
||||||
(load_dir == nullptr && sdmc_load_dir == nullptr)) {
|
(load_dirs.empty() && sdmc_load_dirs.empty())) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
const auto& disabled = Settings::values.disabled_addons[application_id];
|
||||||
std::vector<VirtualDir> patch_dirs = load_dir->GetSubdirectories();
|
std::vector<VirtualDir> patch_dirs;
|
||||||
if (std::find(disabled.cbegin(), disabled.cend(), "SDMC") == disabled.cend()) {
|
for (const auto& load_dir : load_dirs) {
|
||||||
patch_dirs.push_back(sdmc_load_dir);
|
const auto load_patch_dirs = load_dir->GetSubdirectories();
|
||||||
|
patch_dirs.insert(patch_dirs.end(), load_patch_dirs.begin(), load_patch_dirs.end());
|
||||||
}
|
}
|
||||||
std::sort(patch_dirs.begin(), patch_dirs.end(),
|
if (std::find(disabled.cbegin(), disabled.cend(), "SDMC") == disabled.cend()) {
|
||||||
[](const VirtualDir& l, const VirtualDir& r) { return l->GetName() < r->GetName(); });
|
patch_dirs.insert(patch_dirs.end(), sdmc_load_dirs.begin(), sdmc_load_dirs.end());
|
||||||
|
}
|
||||||
|
std::stable_sort(patch_dirs.begin(), patch_dirs.end(), [](const VirtualDir& l, const VirtualDir& r) {
|
||||||
|
return l->GetName() < r->GetName();
|
||||||
|
});
|
||||||
|
|
||||||
std::vector<VirtualDir> layers;
|
std::vector<VirtualDir> layers;
|
||||||
std::vector<VirtualDir> layers_ext;
|
std::vector<VirtualDir> layers_ext;
|
||||||
@@ -597,8 +657,8 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs
|
|||||||
auto romfs = base_romfs;
|
auto romfs = base_romfs;
|
||||||
|
|
||||||
// Game Updates
|
// Game Updates
|
||||||
const auto update_tid = GetUpdateTitleID(title_id);
|
const auto update_tid = GetUpdateTitleIDForContent();
|
||||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
const auto& disabled = Settings::values.disabled_addons[application_id];
|
||||||
|
|
||||||
bool update_disabled = true;
|
bool update_disabled = true;
|
||||||
std::optional<u32> enabled_version;
|
std::optional<u32> enabled_version;
|
||||||
@@ -705,7 +765,7 @@ VirtualFile PatchManager::PatchRomFS(const NCA* base_nca, VirtualFile base_romfs
|
|||||||
|
|
||||||
// LayeredFS
|
// LayeredFS
|
||||||
if (apply_layeredfs) {
|
if (apply_layeredfs) {
|
||||||
ApplyLayeredFS(romfs, title_id, type, fs_controller);
|
ApplyLayeredFS(romfs, title_id, application_id, type, fs_controller);
|
||||||
}
|
}
|
||||||
|
|
||||||
return romfs;
|
return romfs;
|
||||||
@@ -717,10 +777,10 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Patch> out;
|
std::vector<Patch> out;
|
||||||
const auto& disabled = Settings::values.disabled_addons[title_id];
|
const auto& disabled = Settings::values.disabled_addons[application_id];
|
||||||
|
|
||||||
// Game Updates
|
// Game Updates
|
||||||
const auto update_tid = GetUpdateTitleID(title_id);
|
const auto update_tid = GetUpdateTitleIDForContent();
|
||||||
|
|
||||||
std::vector<Patch> external_update_patches;
|
std::vector<Patch> external_update_patches;
|
||||||
|
|
||||||
@@ -869,7 +929,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
.version = "",
|
.version = "",
|
||||||
.type = PatchType::Update,
|
.type = PatchType::Update,
|
||||||
.program_id = title_id,
|
.program_id = title_id,
|
||||||
.title_id = title_id,
|
.title_id = update_tid,
|
||||||
.source = PatchSource::Unknown,
|
.source = PatchSource::Unknown,
|
||||||
.numeric_version = 0};
|
.numeric_version = 0};
|
||||||
|
|
||||||
@@ -895,8 +955,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// General Mods (LayeredFS and IPS)
|
// General Mods (LayeredFS and IPS)
|
||||||
const auto mod_dir = fs_controller.GetModificationLoadRoot(title_id);
|
for (const auto& mod_dir : GetModificationLoadRoots()) {
|
||||||
if (mod_dir != nullptr) {
|
|
||||||
for (auto const& f : mod_dir->GetFiles())
|
for (auto const& f : mod_dir->GetFiles())
|
||||||
if (auto const name = f->GetName(); name.starts_with("cheat_")) {
|
if (auto const name = f->GetName(); name.starts_with("cheat_")) {
|
||||||
auto const mod_disabled = std::find(disabled.begin(), disabled.end(), name) != disabled.end();
|
auto const mod_disabled = std::find(disabled.begin(), disabled.end(), name) != disabled.end();
|
||||||
@@ -963,8 +1022,7 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// SDMC mod directory (RomFS LayeredFS)
|
// SDMC mod directory (RomFS LayeredFS)
|
||||||
const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(title_id);
|
for (const auto& sdmc_mod_dir : GetSDMCModificationLoadRoots()) {
|
||||||
if (sdmc_mod_dir != nullptr) {
|
|
||||||
std::string types;
|
std::string types;
|
||||||
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs")))
|
if (IsDirValidAndNonEmpty(FindSubdirectoryCaseless(sdmc_mod_dir, "exefs")))
|
||||||
AppendCommaIfNotEmpty(types, "LayeredExeFS");
|
AppendCommaIfNotEmpty(types, "LayeredExeFS");
|
||||||
@@ -999,10 +1057,10 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
dlc_match.reserve(dlc_entries_with_origin.size());
|
dlc_match.reserve(dlc_entries_with_origin.size());
|
||||||
for (const auto& [slot, entry] : dlc_entries_with_origin) {
|
for (const auto& [slot, entry] : dlc_entries_with_origin) {
|
||||||
const auto base_tid = GetBaseTitleID(entry.title_id);
|
const auto base_tid = GetBaseTitleID(entry.title_id);
|
||||||
const bool matches_base = base_tid == title_id;
|
const bool matches_base = base_tid == application_id;
|
||||||
if (!matches_base) {
|
if (!matches_base) {
|
||||||
LOG_DEBUG(Loader, "DLC {:016X} base {:016X} doesn't match title {:016X}",
|
LOG_DEBUG(Loader, "DLC {:016X} base {:016X} doesn't match title {:016X}",
|
||||||
entry.title_id, base_tid, title_id);
|
entry.title_id, base_tid, application_id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1077,16 +1135,22 @@ std::vector<Patch> PatchManager::GetPatches(VirtualFile update_raw) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::optional<u32> PatchManager::GetGameVersion() const {
|
std::optional<u32> PatchManager::GetGameVersion() const {
|
||||||
const auto update_tid = GetUpdateTitleID(title_id);
|
const auto update_tid = GetUpdateTitleIDForContent();
|
||||||
if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
|
if (content_provider.HasEntry(update_tid, ContentRecordType::Program)) {
|
||||||
return content_provider.GetEntryVersion(update_tid);
|
return content_provider.GetEntryVersion(update_tid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return content_provider.GetEntryVersion(title_id);
|
if (const auto version = content_provider.GetEntryVersion(title_id); version.has_value()) {
|
||||||
|
return version;
|
||||||
|
}
|
||||||
|
return content_provider.GetEntryVersion(application_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
PatchManager::Metadata PatchManager::GetControlMetadata() const {
|
PatchManager::Metadata PatchManager::GetControlMetadata() const {
|
||||||
const auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control);
|
auto base_control_nca = content_provider.GetEntry(title_id, ContentRecordType::Control);
|
||||||
|
if (base_control_nca == nullptr && application_id != title_id) {
|
||||||
|
base_control_nca = content_provider.GetEntry(application_id, ContentRecordType::Control);
|
||||||
|
}
|
||||||
if (base_control_nca == nullptr) {
|
if (base_control_nca == nullptr) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -1162,8 +1226,14 @@ PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const {
|
|||||||
auto metadata = pm.GetControlMetadata();
|
auto metadata = pm.GetControlMetadata();
|
||||||
if (metadata.first != nullptr)
|
if (metadata.first != nullptr)
|
||||||
return metadata;
|
return metadata;
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(application_id), system.GetFileSystemController(), system.GetContentProvider()};
|
const auto update_id = FileSys::GetUpdateTitleID(application_id);
|
||||||
return pm_update.GetControlMetadata();
|
const auto application_update_id = FileSys::GetUpdateTitleID(GetBaseTitleID(application_id));
|
||||||
|
const FileSys::PatchManager pm_update{update_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||||
|
metadata = pm_update.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr || update_id == application_update_id)
|
||||||
|
return metadata;
|
||||||
|
const FileSys::PatchManager pm_application_update{application_update_id, system.GetFileSystemController(), system.GetContentProvider()};
|
||||||
|
return pm_application_update.GetControlMetadata();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include <memory>
|
#include <memory>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "core/file_sys/nca_metadata.h"
|
||||||
#include "core/file_sys/vfs/vfs_types.h"
|
#include "core/file_sys/vfs/vfs_types.h"
|
||||||
@@ -109,10 +110,14 @@ public:
|
|||||||
[[nodiscard]] static PatchManager::Metadata GetMetadataFromBaseOrUpdate(Core::System& system, u64 application_id) noexcept;
|
[[nodiscard]] static PatchManager::Metadata GetMetadataFromBaseOrUpdate(Core::System& system, u64 application_id) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
[[nodiscard]] u64 GetUpdateTitleIDForContent() const;
|
||||||
|
[[nodiscard]] std::vector<VirtualDir> GetModificationLoadRoots() const;
|
||||||
|
[[nodiscard]] std::vector<VirtualDir> GetSDMCModificationLoadRoots() const;
|
||||||
[[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
[[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
||||||
const std::string& build_id) const;
|
const std::string& build_id) const;
|
||||||
|
|
||||||
u64 title_id;
|
u64 title_id;
|
||||||
|
u64 application_id;
|
||||||
const Service::FileSystem::FileSystemController& fs_controller;
|
const Service::FileSystem::FileSystemController& fs_controller;
|
||||||
const ContentProvider& content_provider;
|
const ContentProvider& content_provider;
|
||||||
};
|
};
|
||||||
|
|||||||
+10
-10
@@ -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,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,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 {
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "core/file_sys/nca_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
@@ -104,8 +105,16 @@ std::unique_ptr<Process> CreateApplicationProcess(std::vector<u8>& out_control,
|
|||||||
|
|
||||||
// TODO(DarkLordZach): When FSController/Game Card Support is added, if
|
// TODO(DarkLordZach): When FSController/Game Card Support is added, if
|
||||||
// current_process_game_card use correct StorageId
|
// current_process_game_card use correct StorageId
|
||||||
launch.base_game_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program));
|
auto base_slot = storage.GetSlotForEntry(launch.title_id, FileSys::ContentRecordType::Program);
|
||||||
launch.update_storage_id = GetStorageIdForFrontendSlot(storage.GetSlotForEntry(FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program));
|
if (!base_slot) {
|
||||||
|
base_slot = storage.GetSlotForEntry(FileSys::GetBaseTitleID(launch.title_id), FileSys::ContentRecordType::Program);
|
||||||
|
}
|
||||||
|
launch.base_game_storage_id = GetStorageIdForFrontendSlot(base_slot);
|
||||||
|
auto update_slot = storage.GetSlotForEntry(FileSys::GetUpdateTitleID(launch.title_id), FileSys::ContentRecordType::Program);
|
||||||
|
if (!update_slot) {
|
||||||
|
update_slot = storage.GetSlotForEntry(FileSys::GetUpdateTitleID(FileSys::GetBaseTitleID(launch.title_id)), FileSys::ContentRecordType::Program);
|
||||||
|
}
|
||||||
|
launch.update_storage_id = GetStorageIdForFrontendSlot(update_slot);
|
||||||
|
|
||||||
system.GetARPManager().Register(launch.title_id, launch, out_control);
|
system.GetARPManager().Register(launch.title_id, launch, out_control);
|
||||||
return process;
|
return process;
|
||||||
|
|||||||
@@ -158,7 +158,7 @@ Result IApplicationFunctions::EnsureSaveData(Out<u64> out_size, Common::UUID use
|
|||||||
LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
|
LOG_INFO(Service_AM, "called, uid={}", user_id.FormattedString());
|
||||||
|
|
||||||
FileSys::SaveDataAttribute attribute{};
|
FileSys::SaveDataAttribute attribute{};
|
||||||
attribute.program_id = m_applet->program_id;
|
attribute.program_id = FileSys::GetBaseTitleID(m_applet->program_id);
|
||||||
attribute.user_id = user_id.AsU128();
|
attribute.user_id = user_id.AsU128();
|
||||||
attribute.type = FileSys::SaveDataType::Account;
|
attribute.type = FileSys::SaveDataType::Account;
|
||||||
|
|
||||||
@@ -238,7 +238,7 @@ Result IApplicationFunctions::ExtendSaveData(Out<u64> out_required_size, FileSys
|
|||||||
static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size);
|
static_cast<u8>(type), user_id.FormattedString(), normal_size, journal_size);
|
||||||
|
|
||||||
system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
|
system.GetFileSystemController().OpenSaveDataController()->WriteSaveDataSize(
|
||||||
type, m_applet->program_id, user_id.AsU128(), {normal_size, journal_size});
|
type, FileSys::GetBaseTitleID(m_applet->program_id), user_id.AsU128(), {normal_size, journal_size});
|
||||||
|
|
||||||
// The following value is used to indicate the amount of space remaining on failure
|
// The following value is used to indicate the amount of space remaining on failure
|
||||||
// due to running out of space. Since we always succeed, this should be 0.
|
// due to running out of space. Since we always succeed, this should be 0.
|
||||||
@@ -252,7 +252,7 @@ Result IApplicationFunctions::GetSaveDataSize(Out<u64> out_normal_size, Out<u64>
|
|||||||
LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString());
|
LOG_DEBUG(Service_AM, "called with type={} user_id={}", type, user_id.FormattedString());
|
||||||
|
|
||||||
const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
|
const auto size = system.GetFileSystemController().OpenSaveDataController()->ReadSaveDataSize(
|
||||||
type, m_applet->program_id, user_id.AsU128());
|
type, FileSys::GetBaseTitleID(m_applet->program_id), user_id.AsU128());
|
||||||
|
|
||||||
*out_normal_size = size.normal;
|
*out_normal_size = size.normal;
|
||||||
*out_journal_size = size.journal;
|
*out_journal_size = size.journal;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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!");
|
||||||
|
|||||||
@@ -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-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -10,6 +7,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 +34,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 +53,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,
|
||||||
@@ -72,10 +70,10 @@ Result IAudioInManager::ListAudioInsAutoFiltered(
|
|||||||
}
|
}
|
||||||
|
|
||||||
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");
|
||||||
|
|
||||||
@@ -106,7 +104,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())};
|
||||||
|
|||||||
@@ -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},
|
||||||
@@ -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");
|
||||||
@@ -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_} {}
|
||||||
|
|||||||
@@ -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_,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/bis_factory.h"
|
#include "core/file_sys/bis_factory.h"
|
||||||
#include "core/file_sys/card_image.h"
|
#include "core/file_sys/card_image.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
@@ -32,10 +33,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,
|
||||||
@@ -343,7 +340,7 @@ Result FileSystemController::RegisterProcess(
|
|||||||
registrations.emplace(process_id, Registration{
|
registrations.emplace(process_id, Registration{
|
||||||
.program_id = program_id,
|
.program_id = program_id,
|
||||||
.romfs_factory = std::move(romfs_factory),
|
.romfs_factory = std::move(romfs_factory),
|
||||||
.save_data_factory = CreateSaveDataFactory(program_id),
|
.save_data_factory = CreateSaveDataFactory(FileSys::GetBaseTitleID(program_id)),
|
||||||
});
|
});
|
||||||
|
|
||||||
LOG_DEBUG(Service_FS, "Registered for process {}", process_id);
|
LOG_DEBUG(Service_FS, "Registered for process {}", process_id);
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/fs_directory.h"
|
#include "core/file_sys/fs_directory.h"
|
||||||
@@ -313,7 +314,7 @@ Result FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId(OutInterface<IFileSyste
|
|||||||
FileSys::ResultInvalidArgument);
|
FileSys::ResultInvalidArgument);
|
||||||
|
|
||||||
if (attribute.program_id == 0) {
|
if (attribute.program_id == 0) {
|
||||||
attribute.program_id = program_id;
|
attribute.program_id = FileSys::GetBaseTitleID(program_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
FileSys::VirtualDir dir{};
|
FileSys::VirtualDir dir{};
|
||||||
|
|||||||
@@ -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_)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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 {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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"));
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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());
|
||||||
|
|||||||
@@ -70,6 +70,15 @@ std::optional<IndexedProgram> ResolveIndexedProgram(Core::System& system, u64 pr
|
|||||||
return IndexedProgram{std::move(update), target_id, true};
|
return IndexedProgram{std::move(update), target_id, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto application_update_id =
|
||||||
|
FileSys::GetUpdateTitleID(FileSys::GetBaseTitleID(target_id));
|
||||||
|
if (application_update_id != update_id) {
|
||||||
|
if (auto update = provider.GetEntryRaw(application_update_id, FileSys::ContentRecordType::Program)) {
|
||||||
|
LOG_INFO(Loader, "Program index {} has no base program, loading it from application update {:016X}", program_index, application_update_id);
|
||||||
|
return IndexedProgram{std::move(update), target_id, true};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LOG_WARNING(Loader, "No program NCA for {:016X} (index {}), falling back to the container",
|
LOG_WARNING(Loader, "No program NCA for {:016X} (index {}), falling back to the container",
|
||||||
target_id, program_index);
|
target_id, program_index);
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include "common/hex_util.h"
|
#include "common/hex_util.h"
|
||||||
#include "common/scope_exit.h"
|
#include "common/scope_exit.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/nca_metadata.h"
|
#include "core/file_sys/nca_metadata.h"
|
||||||
@@ -76,8 +77,13 @@ AppLoader_NCA::LoadResult AppLoader_NCA::Load(Kernel::KProcess& process, Core::S
|
|||||||
LOG_INFO(Loader, "No ExeFS found in NCA, looking for ExeFS from update");
|
LOG_INFO(Loader, "No ExeFS found in NCA, looking for ExeFS from update");
|
||||||
|
|
||||||
const auto& installed = system.GetContentProvider();
|
const auto& installed = system.GetContentProvider();
|
||||||
const auto update_nca = installed.GetEntry(FileSys::GetUpdateTitleID(nca->GetTitleId()),
|
const auto program_update_id = FileSys::GetUpdateTitleID(nca->GetTitleId());
|
||||||
FileSys::ContentRecordType::Program);
|
auto update_nca = installed.GetEntry(program_update_id, FileSys::ContentRecordType::Program);
|
||||||
|
if (update_nca == nullptr) {
|
||||||
|
update_nca = installed.GetEntry(
|
||||||
|
FileSys::GetUpdateTitleID(FileSys::GetBaseTitleID(nca->GetTitleId())),
|
||||||
|
FileSys::ContentRecordType::Program);
|
||||||
|
}
|
||||||
|
|
||||||
if (update_nca) {
|
if (update_nca) {
|
||||||
exefs = update_nca->GetExeFS();
|
exefs = update_nca->GetExeFS();
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -186,8 +186,13 @@ ResultStatus AppLoader_NSP::ReadUpdateRaw(FileSys::VirtualFile& out_file) {
|
|||||||
return ResultStatus::ErrorNoPackedUpdate;
|
return ResultStatus::ErrorNoPackedUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto read = nsp->GetNCAFile(FileSys::GetUpdateTitleID(nsp->GetProgramTitleID()),
|
const auto program_update_id = FileSys::GetUpdateTitleID(nsp->GetProgramTitleID());
|
||||||
FileSys::ContentRecordType::Program);
|
auto read = nsp->GetNCAFile(program_update_id, FileSys::ContentRecordType::Program);
|
||||||
|
if (read == nullptr) {
|
||||||
|
read = nsp->GetNCAFile(
|
||||||
|
FileSys::GetUpdateTitleID(FileSys::GetBaseTitleID(nsp->GetProgramTitleID())),
|
||||||
|
FileSys::ContentRecordType::Program);
|
||||||
|
}
|
||||||
|
|
||||||
if (read == nullptr) {
|
if (read == nullptr) {
|
||||||
return ResultStatus::ErrorNoPackedUpdate;
|
return ResultStatus::ErrorNoPackedUpdate;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/file_sys/card_image.h"
|
#include "core/file_sys/card_image.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/content_archive.h"
|
#include "core/file_sys/content_archive.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
#include "core/file_sys/patch_manager.h"
|
#include "core/file_sys/patch_manager.h"
|
||||||
@@ -137,8 +138,13 @@ ResultStatus AppLoader_XCI::ReadUpdateRaw(FileSys::VirtualFile& out_file) {
|
|||||||
return ResultStatus::ErrorXCIMissingProgramNCA;
|
return ResultStatus::ErrorXCIMissingProgramNCA;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto read = xci->GetSecurePartitionNSP()->GetNCAFile(
|
const auto program_update_id = FileSys::GetUpdateTitleID(program_id);
|
||||||
FileSys::GetUpdateTitleID(program_id), FileSys::ContentRecordType::Program);
|
auto read = xci->GetSecurePartitionNSP()->GetNCAFile(program_update_id, FileSys::ContentRecordType::Program);
|
||||||
|
if (read == nullptr) {
|
||||||
|
read = xci->GetSecurePartitionNSP()->GetNCAFile(
|
||||||
|
FileSys::GetUpdateTitleID(FileSys::GetBaseTitleID(program_id)),
|
||||||
|
FileSys::ContentRecordType::Program);
|
||||||
|
}
|
||||||
if (read == nullptr) {
|
if (read == nullptr) {
|
||||||
return ResultStatus::ErrorNoPackedUpdate;
|
return ResultStatus::ErrorNoPackedUpdate;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
||||||
@@ -56,13 +56,14 @@ inline bool RemoveDLC(const Service::FileSystem::FileSystemController& fs_contro
|
|||||||
*/
|
*/
|
||||||
inline size_t RemoveAllDLC(Core::System& system, const u64 program_id) {
|
inline size_t RemoveAllDLC(Core::System& system, const u64 program_id) {
|
||||||
size_t count{};
|
size_t count{};
|
||||||
|
const auto application_id = FileSys::GetBaseTitleID(program_id);
|
||||||
const auto& fs_controller = system.GetFileSystemController();
|
const auto& fs_controller = system.GetFileSystemController();
|
||||||
const auto dlc_entries = system.GetContentProvider().ListEntriesFilter(
|
const auto dlc_entries = system.GetContentProvider().ListEntriesFilter(
|
||||||
FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
|
FileSys::TitleType::AOC, FileSys::ContentRecordType::Data);
|
||||||
std::vector<u64> program_dlc_entries;
|
std::vector<u64> program_dlc_entries;
|
||||||
|
|
||||||
for (const auto& entry : dlc_entries) {
|
for (const auto& entry : dlc_entries) {
|
||||||
if (FileSys::GetBaseTitleID(entry.title_id) == program_id) {
|
if (FileSys::GetBaseTitleID(entry.title_id) == application_id) {
|
||||||
program_dlc_entries.push_back(entry.title_id);
|
program_dlc_entries.push_back(entry.title_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,9 +84,17 @@ inline size_t RemoveAllDLC(Core::System& system, const u64 program_id) {
|
|||||||
*/
|
*/
|
||||||
inline bool RemoveUpdate(const Service::FileSystem::FileSystemController& fs_controller,
|
inline bool RemoveUpdate(const Service::FileSystem::FileSystemController& fs_controller,
|
||||||
const u64 program_id) {
|
const u64 program_id) {
|
||||||
const auto update_id = program_id | 0x800;
|
const auto remove_update = [&fs_controller](u64 update_id) {
|
||||||
return fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
|
return fs_controller.GetUserNANDContents()->RemoveExistingEntry(update_id) ||
|
||||||
fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id);
|
fs_controller.GetSDMCContents()->RemoveExistingEntry(update_id);
|
||||||
|
};
|
||||||
|
const auto update_id = FileSys::GetUpdateTitleID(program_id);
|
||||||
|
const auto application_update_id =
|
||||||
|
FileSys::GetUpdateTitleID(FileSys::GetBaseTitleID(program_id));
|
||||||
|
if (update_id != application_update_id && remove_update(update_id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return remove_update(application_update_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,15 +120,26 @@ inline bool RemoveBaseContent(const Service::FileSystem::FileSystemController& f
|
|||||||
inline bool RemoveMod(const Service::FileSystem::FileSystemController& fs_controller,
|
inline bool RemoveMod(const Service::FileSystem::FileSystemController& fs_controller,
|
||||||
const u64 program_id, const std::string& mod_name) {
|
const u64 program_id, const std::string& mod_name) {
|
||||||
// Check general Mods (LayeredFS and IPS)
|
// Check general Mods (LayeredFS and IPS)
|
||||||
const auto mod_dir = fs_controller.GetModificationLoadRoot(program_id);
|
const auto remove_from_root = [&mod_name](const auto& root) {
|
||||||
if (mod_dir != nullptr) {
|
return root != nullptr && root->DeleteSubdirectoryRecursive(mod_name);
|
||||||
return mod_dir->DeleteSubdirectoryRecursive(mod_name);
|
};
|
||||||
|
if (remove_from_root(fs_controller.GetModificationLoadRoot(program_id))) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (FileSys::GetBaseTitleID(program_id) != program_id &&
|
||||||
|
remove_from_root(
|
||||||
|
fs_controller.GetModificationLoadRoot(FileSys::GetBaseTitleID(program_id)))) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check SDMC mod directory (RomFS LayeredFS)
|
// Check SDMC mod directory (RomFS LayeredFS)
|
||||||
const auto sdmc_mod_dir = fs_controller.GetSDMCModificationLoadRoot(program_id);
|
if (remove_from_root(fs_controller.GetSDMCModificationLoadRoot(program_id))) {
|
||||||
if (sdmc_mod_dir != nullptr) {
|
return true;
|
||||||
return sdmc_mod_dir->DeleteSubdirectoryRecursive(mod_name);
|
}
|
||||||
|
if (FileSys::GetBaseTitleID(program_id) != program_id &&
|
||||||
|
remove_from_root(
|
||||||
|
fs_controller.GetSDMCModificationLoadRoot(FileSys::GetBaseTitleID(program_id)))) {
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/fs/fs_types.h"
|
#include "common/fs/fs_types.h"
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "frontend_common/data_manager.h"
|
#include "frontend_common/data_manager.h"
|
||||||
#include "mod_manager.h"
|
#include "mod_manager.h"
|
||||||
|
|
||||||
@@ -40,7 +41,7 @@ std::vector<std::filesystem::path> GetModFolder(const std::string& root) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ModInstallResult InstallMod(const std::filesystem::path& path, const u64 program_id, const bool copy) {
|
ModInstallResult InstallMod(const std::filesystem::path& path, const u64 program_id, const bool copy) {
|
||||||
const auto program_id_string = fmt::format("{:016X}", program_id);
|
const auto program_id_string = fmt::format("{:016X}", FileSys::GetBaseTitleID(program_id));
|
||||||
const auto mod_name = path.filename();
|
const auto mod_name = path.filename();
|
||||||
const auto mod_dir =
|
const auto mod_dir =
|
||||||
DataManager::GetDataDir(DataManager::DataDir::Mods) / program_id_string / mod_name;
|
DataManager::GetDataDir(DataManager::DataDir::Mods) / program_id_string / mod_name;
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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() {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -832,7 +832,7 @@ void Room::RoomImpl::HandleProxyPacket(const ENetEvent* event) {
|
|||||||
|
|
||||||
in_packet.IgnoreBytes(sizeof(u8)); // Protocol
|
in_packet.IgnoreBytes(sizeof(u8)); // Protocol
|
||||||
|
|
||||||
bool broadcast = false;
|
bool broadcast;
|
||||||
in_packet.Read(broadcast); // Broadcast
|
in_packet.Read(broadcast); // Broadcast
|
||||||
|
|
||||||
Packet out_packet;
|
Packet out_packet;
|
||||||
@@ -886,7 +886,7 @@ void Room::RoomImpl::HandleLdnPacket(const ENetEvent* event) {
|
|||||||
IPv4Address remote_ip;
|
IPv4Address remote_ip;
|
||||||
in_packet.Read(remote_ip); // Remote IP
|
in_packet.Read(remote_ip); // Remote IP
|
||||||
|
|
||||||
bool broadcast = false;
|
bool broadcast;
|
||||||
in_packet.Read(broadcast); // Broadcast
|
in_packet.Read(broadcast); // Broadcast
|
||||||
|
|
||||||
Packet out_packet;
|
Packet out_packet;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
#include "common/fs/path_util.h"
|
#include "common/fs/path_util.h"
|
||||||
|
#include "core/file_sys/common_funcs.h"
|
||||||
#include "core/file_sys/savedata_factory.h"
|
#include "core/file_sys/savedata_factory.h"
|
||||||
#include "core/hle/service/am/am_types.h"
|
#include "core/hle/service/am/am_types.h"
|
||||||
#include "frontend_common/content_manager.h"
|
#include "frontend_common/content_manager.h"
|
||||||
@@ -305,6 +306,7 @@ void RemoveAllTransferableShaderCaches(u64 program_id) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path) {
|
void RemoveCustomConfiguration(u64 program_id, const std::string& game_path) {
|
||||||
|
program_id = FileSys::GetBaseTitleID(program_id);
|
||||||
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
|
const auto file_path = std::filesystem::path(Common::FS::ToU8String(game_path));
|
||||||
const auto config_file_name =
|
const auto config_file_name =
|
||||||
program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini")
|
program_id == 0 ? Common::FS::PathToUTF8String(file_path.filename()).append(".ini")
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
@@ -48,6 +45,11 @@ void GetCbuf(EmitContext& ctx, IR::Inst& inst, const IR::Value& binding, ScalarU
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsInputArray(Stage stage) {
|
||||||
|
return stage == Stage::Geometry || stage == Stage::TessellationControl ||
|
||||||
|
stage == Stage::TessellationEval;
|
||||||
|
}
|
||||||
|
|
||||||
std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) {
|
std::string VertexIndex(EmitContext& ctx, ScalarU32 vertex) {
|
||||||
return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
|
return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "shader_recompiler/stage.h"
|
|
||||||
#include "shader_recompiler/backend/glasm/reg_alloc.h"
|
#include "shader_recompiler/backend/glasm/reg_alloc.h"
|
||||||
|
|
||||||
namespace Shader::IR {
|
namespace Shader::IR {
|
||||||
@@ -19,11 +18,6 @@ class Value;
|
|||||||
|
|
||||||
namespace Shader::Backend::GLASM {
|
namespace Shader::Backend::GLASM {
|
||||||
|
|
||||||
[[nodiscard]] inline bool IsInputArray(Stage stage) {
|
|
||||||
return stage == Stage::Geometry || stage == Stage::TessellationControl
|
|
||||||
|| stage == Stage::TessellationEval;
|
|
||||||
}
|
|
||||||
|
|
||||||
class EmitContext;
|
class EmitContext;
|
||||||
|
|
||||||
// Microinstruction emitters
|
// Microinstruction emitters
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -10,92 +7,94 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::GLASM {
|
namespace Shader::Backend::GLASM {
|
||||||
|
|
||||||
|
#define NotImplemented() throw NotImplementedException("GLASM instruction {}", __LINE__)
|
||||||
|
|
||||||
void EmitGetRegister(EmitContext& ctx) {
|
void EmitGetRegister(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetRegister(EmitContext& ctx) {
|
void EmitSetRegister(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetPred(EmitContext& ctx) {
|
void EmitGetPred(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetPred(EmitContext& ctx) {
|
void EmitSetPred(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetGotoVariable(EmitContext& ctx) {
|
void EmitSetGotoVariable(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetGotoVariable(EmitContext& ctx) {
|
void EmitGetGotoVariable(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetIndirectBranchVariable(EmitContext& ctx) {
|
void EmitSetIndirectBranchVariable(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetIndirectBranchVariable(EmitContext& ctx) {
|
void EmitGetIndirectBranchVariable(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetZFlag(EmitContext& ctx) {
|
void EmitGetZFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetSFlag(EmitContext& ctx) {
|
void EmitGetSFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetCFlag(EmitContext& ctx) {
|
void EmitGetCFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetOFlag(EmitContext& ctx) {
|
void EmitGetOFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetZFlag(EmitContext& ctx) {
|
void EmitSetZFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetSFlag(EmitContext& ctx) {
|
void EmitSetSFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetCFlag(EmitContext& ctx) {
|
void EmitSetCFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitSetOFlag(EmitContext& ctx) {
|
void EmitSetOFlag(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetZeroFromOp(EmitContext& ctx) {
|
void EmitGetZeroFromOp(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetSignFromOp(EmitContext& ctx) {
|
void EmitGetSignFromOp(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetCarryFromOp(EmitContext& ctx) {
|
void EmitGetCarryFromOp(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetOverflowFromOp(EmitContext& ctx) {
|
void EmitGetOverflowFromOp(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetSparseFromOp(EmitContext& ctx) {
|
void EmitGetSparseFromOp(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitGetInBoundsFromOp(EmitContext& ctx) {
|
void EmitGetInBoundsFromOp(EmitContext& ctx) {
|
||||||
throw NotImplementedException("GLASM instruction {}", __LINE__);
|
NotImplemented();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Shader::Backend::GLASM
|
} // namespace Shader::Backend::GLASM
|
||||||
|
|||||||
@@ -1,12 +1,8 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include "shader_recompiler/backend/bindings.h"
|
#include "shader_recompiler/backend/bindings.h"
|
||||||
#include "shader_recompiler/backend/glasm/emit_glasm.h"
|
#include "shader_recompiler/backend/glasm/emit_glasm.h"
|
||||||
#include "shader_recompiler/backend/glasm/emit_glasm_instructions.h"
|
|
||||||
#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
|
#include "shader_recompiler/backend/glasm/glasm_emit_context.h"
|
||||||
#include "shader_recompiler/frontend/ir/program.h"
|
#include "shader_recompiler/frontend/ir/program.h"
|
||||||
#include "shader_recompiler/profile.h"
|
#include "shader_recompiler/profile.h"
|
||||||
@@ -25,6 +21,11 @@ std::string_view InterpDecorator(Interpolation interp) {
|
|||||||
}
|
}
|
||||||
throw InvalidArgument("Invalid interpolation {}", interp);
|
throw InvalidArgument("Invalid interpolation {}", interp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsInputArray(Stage stage) {
|
||||||
|
return stage == Stage::Geometry || stage == Stage::TessellationControl ||
|
||||||
|
stage == Stage::TessellationEval;
|
||||||
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
|
EmitContext::EmitContext(IR::Program& program, Bindings& bindings, const Profile& profile_,
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -12,13 +9,14 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
namespace {
|
namespace {
|
||||||
|
constexpr std::string_view SWIZZLE{"xyzw"};
|
||||||
void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view composite,
|
void CompositeInsert(EmitContext& ctx, std::string_view result, std::string_view composite,
|
||||||
std::string_view object, u32 index) {
|
std::string_view object, u32 index) {
|
||||||
if (result == composite) {
|
if (result == composite) {
|
||||||
// The result is aliased with the composite
|
// The result is aliased with the composite
|
||||||
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
|
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
|
||||||
} else {
|
} else {
|
||||||
ctx.Add("{}={};{}.{}={};", result, composite, result, "xyzw"[index], object);
|
ctx.Add("{}={};{}.{}={};", result, composite, result, SWIZZLE[index], object);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
@@ -40,17 +38,17 @@ void EmitCompositeConstructU32x4(EmitContext& ctx, IR::Inst& inst, std::string_v
|
|||||||
|
|
||||||
void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeExtractU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.AddU32("{}={}.{};", inst, composite, "xyzw"[index]);
|
ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeExtractU32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.AddU32("{}={}.{};", inst, composite, "xyzw"[index]);
|
ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeExtractU32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.AddU32("{}={}.{};", inst, composite, "xyzw"[index]);
|
ctx.AddU32("{}={}.{};", inst, composite, SWIZZLE[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeInsertU32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
@@ -148,17 +146,17 @@ void EmitCompositeConstructF32x4(EmitContext& ctx, IR::Inst& inst, std::string_v
|
|||||||
|
|
||||||
void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeExtractF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.AddF32("{}={}.{};", inst, composite, "xyzw"[index]);
|
ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeExtractF32x3(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.AddF32("{}={}.{};", inst, composite, "xyzw"[index]);
|
ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeExtractF32x4(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.AddF32("{}={}.{};", inst, composite, "xyzw"[index]);
|
ctx.AddF32("{}={}.{};", inst, composite, SWIZZLE[index]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
void EmitCompositeInsertF32x2(EmitContext& ctx, IR::Inst& inst, std::string_view composite,
|
||||||
@@ -205,16 +203,16 @@ void EmitCompositeExtractF64x4([[maybe_unused]] EmitContext& ctx) {
|
|||||||
|
|
||||||
void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object,
|
void EmitCompositeInsertF64x2(EmitContext& ctx, std::string_view composite, std::string_view object,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
|
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object,
|
void EmitCompositeInsertF64x3(EmitContext& ctx, std::string_view composite, std::string_view object,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
|
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object,
|
void EmitCompositeInsertF64x4(EmitContext& ctx, std::string_view composite, std::string_view object,
|
||||||
u32 index) {
|
u32 index) {
|
||||||
ctx.Add("{}.{}={};", composite, "xyzw"[index], object);
|
ctx.Add("{}.{}={};", composite, SWIZZLE[index], object);
|
||||||
}
|
}
|
||||||
} // namespace Shader::Backend::GLSL
|
} // namespace Shader::Backend::GLSL
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -14,13 +11,14 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
namespace {
|
namespace {
|
||||||
|
constexpr char SWIZZLE[]{"xyzw"};
|
||||||
|
|
||||||
u32 CbufIndex(u32 offset) {
|
u32 CbufIndex(u32 offset) {
|
||||||
return (offset / 4) % 4;
|
return (offset / 4) % 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
char OffsetSwizzle(u32 offset) {
|
char OffsetSwizzle(u32 offset) {
|
||||||
return "xyzw"[CbufIndex(offset)];
|
return SWIZZLE[CbufIndex(offset)];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInputArray(Stage stage) {
|
bool IsInputArray(Stage stage) {
|
||||||
@@ -32,6 +30,10 @@ std::string InputVertexIndex(EmitContext& ctx, std::string_view vertex) {
|
|||||||
return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
|
return IsInputArray(ctx.stage) ? fmt::format("[{}]", vertex) : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string_view OutputVertexIndex(EmitContext& ctx) {
|
||||||
|
return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
|
||||||
|
}
|
||||||
|
|
||||||
std::string ChooseCbuf(EmitContext& ctx, const IR::Value& binding, std::string_view index) {
|
std::string ChooseCbuf(EmitContext& ctx, const IR::Value& binding, std::string_view index) {
|
||||||
if (binding.IsImmediate()) {
|
if (binding.IsImmediate()) {
|
||||||
return fmt::format("{}_cbuf{}[{}]", ctx.stage_name, binding.U32(), index);
|
return fmt::format("{}_cbuf{}[{}]", ctx.stage_name, binding.U32(), index);
|
||||||
@@ -277,7 +279,7 @@ void EmitSetAttribute(EmitContext& ctx, IR::Attribute attr, std::string_view val
|
|||||||
const u32 index{IR::GenericAttributeIndex(attr)};
|
const u32 index{IR::GenericAttributeIndex(attr)};
|
||||||
const u32 attr_element{IR::GenericAttributeElement(attr)};
|
const u32 attr_element{IR::GenericAttributeElement(attr)};
|
||||||
const GenericElementInfo& info{ctx.output_generics.at(index).at(attr_element)};
|
const GenericElementInfo& info{ctx.output_generics.at(index).at(attr_element)};
|
||||||
const auto output_decorator = ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
|
const auto output_decorator{OutputVertexIndex(ctx)};
|
||||||
if (info.num_components == 1) {
|
if (info.num_components == 1) {
|
||||||
ctx.Add("{}{}={};", info.name, output_decorator, value);
|
ctx.Add("{}{}={};", info.name, output_decorator, value);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -13,13 +10,14 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
namespace {
|
namespace {
|
||||||
|
constexpr char cas_loop[]{"for(;;){{uint old_value={};uint "
|
||||||
|
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
|
||||||
|
"if(cas_result==old_value){{break;}}}}"};
|
||||||
|
|
||||||
void SsboWriteCas(EmitContext& ctx, const IR::Value& binding, std::string_view offset_var,
|
void SsboWriteCas(EmitContext& ctx, const IR::Value& binding, std::string_view offset_var,
|
||||||
std::string_view value, std::string_view bit_offset, u32 num_bits) {
|
std::string_view value, std::string_view bit_offset, u32 num_bits) {
|
||||||
const auto ssbo{fmt::format("{}_ssbo{}[{}>>2]", ctx.stage_name, binding.U32(), offset_var)};
|
const auto ssbo{fmt::format("{}_ssbo{}[{}>>2]", ctx.stage_name, binding.U32(), offset_var)};
|
||||||
ctx.Add(
|
ctx.Add(cas_loop, ssbo, ssbo, ssbo, value, bit_offset, num_bits);
|
||||||
"for(;;){{uint old_value={};uint "
|
|
||||||
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
|
|
||||||
"if(cas_result==old_value){{break;}}}}", ssbo, ssbo, ssbo, value, bit_offset, num_bits);
|
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -10,13 +7,14 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
namespace {
|
namespace {
|
||||||
|
constexpr char cas_loop[]{"for(;;){{uint old_value={};uint "
|
||||||
|
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
|
||||||
|
"if(cas_result==old_value){{break;}}}}"};
|
||||||
|
|
||||||
void SharedWriteCas(EmitContext& ctx, std::string_view offset, std::string_view value,
|
void SharedWriteCas(EmitContext& ctx, std::string_view offset, std::string_view value,
|
||||||
std::string_view bit_offset, u32 num_bits) {
|
std::string_view bit_offset, u32 num_bits) {
|
||||||
const auto smem{fmt::format("smem[{}>>2]", offset)};
|
const auto smem{fmt::format("smem[{}>>2]", offset)};
|
||||||
ctx.Add(
|
ctx.Add(cas_loop, smem, smem, smem, value, bit_offset, num_bits);
|
||||||
"for(;;){{uint old_value={};uint "
|
|
||||||
"cas_result=atomicCompSwap({},old_value,bitfieldInsert({},{},{},{}));"
|
|
||||||
"if(cas_result==old_value){{break;}}}}", smem, smem, smem, value, bit_offset, num_bits);
|
|
||||||
}
|
}
|
||||||
} // Anonymous namespace
|
} // Anonymous namespace
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -12,6 +9,9 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::GLSL {
|
namespace Shader::Backend::GLSL {
|
||||||
namespace {
|
namespace {
|
||||||
|
std::string_view OutputVertexIndex(EmitContext& ctx) {
|
||||||
|
return ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
|
||||||
|
}
|
||||||
|
|
||||||
void InitializeOutputVaryings(EmitContext& ctx) {
|
void InitializeOutputVaryings(EmitContext& ctx) {
|
||||||
if (ctx.uses_geometry_passthrough) {
|
if (ctx.uses_geometry_passthrough) {
|
||||||
@@ -25,7 +25,7 @@ void InitializeOutputVaryings(EmitContext& ctx) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const auto& info_array{ctx.output_generics.at(index)};
|
const auto& info_array{ctx.output_generics.at(index)};
|
||||||
const auto output_decorator = ctx.stage == Stage::TessellationControl ? "[gl_InvocationID]" : "";
|
const auto output_decorator{OutputVertexIndex(ctx)};
|
||||||
size_t element{};
|
size_t element{};
|
||||||
while (element < info_array.size()) {
|
while (element < info_array.size()) {
|
||||||
const auto& info{info_array.at(element)};
|
const auto& info{info_array.at(element)};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-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,7 +9,7 @@
|
|||||||
|
|
||||||
namespace Shader::Backend::SPIRV {
|
namespace Shader::Backend::SPIRV {
|
||||||
namespace {
|
namespace {
|
||||||
Id DecorateNoContraction(EmitContext& ctx, IR::Inst* inst, Id op) {
|
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id op) {
|
||||||
const auto flags{inst->Flags<IR::FpControl>()};
|
const auto flags{inst->Flags<IR::FpControl>()};
|
||||||
if (flags.no_contraction) {
|
if (flags.no_contraction) {
|
||||||
ctx.Decorate(op, spv::Decoration::NoContraction);
|
ctx.Decorate(op, spv::Decoration::NoContraction);
|
||||||
@@ -61,27 +61,27 @@ Id EmitFPAbs64(EmitContext& ctx, Id value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
Id EmitFPAdd16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFAdd(ctx.F16[1], a, b));
|
return Decorate(ctx, inst, ctx.OpFAdd(ctx.F16[1], a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
Id EmitFPAdd32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFAdd(ctx.F32[1], a, b));
|
return Decorate(ctx, inst, ctx.OpFAdd(ctx.F32[1], a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
Id EmitFPAdd64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFAdd(ctx.F64[1], a, b));
|
return Decorate(ctx, inst, ctx.OpFAdd(ctx.F64[1], a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
Id EmitFPFma16(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFma(ctx.F16[1], a, b, c));
|
return Decorate(ctx, inst, ctx.OpFma(ctx.F16[1], a, b, c));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
Id EmitFPFma32(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFma(ctx.F32[1], a, b, c));
|
return Decorate(ctx, inst, ctx.OpFma(ctx.F32[1], a, b, c));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
Id EmitFPFma64(EmitContext& ctx, IR::Inst* inst, Id a, Id b, Id c) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c));
|
return Decorate(ctx, inst, ctx.OpFma(ctx.F64[1], a, b, c));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPMax32(EmitContext& ctx, Id a, Id b) {
|
Id EmitFPMax32(EmitContext& ctx, Id a, Id b) {
|
||||||
@@ -101,15 +101,15 @@ Id EmitFPMin64(EmitContext& ctx, Id a, Id b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
Id EmitFPMul16(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b));
|
return Decorate(ctx, inst, ctx.OpFMul(ctx.F16[1], a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
Id EmitFPMul32(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFMul(ctx.F32[1], a, b));
|
return Decorate(ctx, inst, ctx.OpFMul(ctx.F32[1], a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
Id EmitFPMul64(EmitContext& ctx, IR::Inst* inst, Id a, Id b) {
|
||||||
return DecorateNoContraction(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b));
|
return Decorate(ctx, inst, ctx.OpFMul(ctx.F64[1], a, b));
|
||||||
}
|
}
|
||||||
|
|
||||||
Id EmitFPNeg16(EmitContext& ctx, Id value) {
|
Id EmitFPNeg16(EmitContext& ctx, Id value) {
|
||||||
|
|||||||
@@ -338,7 +338,7 @@ bool IsTextureInteger(EmitContext& ctx, const IR::TextureInstInfo& info) {
|
|||||||
return ctx.textures.at(info.descriptor_index).is_integer;
|
return ctx.textures.at(info.descriptor_index).is_integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Id DecorateRelaxedPrecision(EmitContext& ctx, IR::Inst* inst, Id sample) {
|
Id Decorate(EmitContext& ctx, IR::Inst* inst, Id sample) {
|
||||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||||
if (info.relaxed_precision != 0) {
|
if (info.relaxed_precision != 0) {
|
||||||
ctx.Decorate(sample, spv::Decoration::RelaxedPrecision);
|
ctx.Decorate(sample, spv::Decoration::RelaxedPrecision);
|
||||||
@@ -351,14 +351,14 @@ Id Emit(MethodPtrType sparse_ptr, MethodPtrType non_sparse_ptr, EmitContext& ctx
|
|||||||
Id result_type, Args&&... args) {
|
Id result_type, Args&&... args) {
|
||||||
IR::Inst* const sparse{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
|
IR::Inst* const sparse{inst->GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp)};
|
||||||
if (!sparse) {
|
if (!sparse) {
|
||||||
return DecorateRelaxedPrecision(ctx, inst, (ctx.*non_sparse_ptr)(result_type, std::forward<Args>(args)...));
|
return Decorate(ctx, inst, (ctx.*non_sparse_ptr)(result_type, std::forward<Args>(args)...));
|
||||||
}
|
}
|
||||||
const Id struct_type{ctx.TypeStruct(ctx.U32[1], result_type)};
|
const Id struct_type{ctx.TypeStruct(ctx.U32[1], result_type)};
|
||||||
const Id sample{(ctx.*sparse_ptr)(struct_type, std::forward<Args>(args)...)};
|
const Id sample{(ctx.*sparse_ptr)(struct_type, std::forward<Args>(args)...)};
|
||||||
const Id resident_code{ctx.OpCompositeExtract(ctx.U32[1], sample, 0U)};
|
const Id resident_code{ctx.OpCompositeExtract(ctx.U32[1], sample, 0U)};
|
||||||
sparse->SetDefinition(ctx.OpImageSparseTexelsResident(ctx.U1, resident_code));
|
sparse->SetDefinition(ctx.OpImageSparseTexelsResident(ctx.U1, resident_code));
|
||||||
sparse->Invalidate();
|
sparse->Invalidate();
|
||||||
DecorateRelaxedPrecision(ctx, inst, sample);
|
Decorate(ctx, inst, sample);
|
||||||
return ctx.OpCompositeExtract(result_type, sample, 1U);
|
return ctx.OpCompositeExtract(result_type, sample, 1U);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user