Compare commits
40 Commits
android-19
...
android-19
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2addc2e59 | ||
|
|
bd1e144403 | ||
|
|
d8eebc23e6 | ||
|
|
170248be67 | ||
|
|
915efa4236 | ||
|
|
4548e5ae1d | ||
|
|
46c2435235 | ||
|
|
2c29c2b8dd | ||
|
|
16abda59be | ||
|
|
90ab89a0b0 | ||
|
|
6531ad56a6 | ||
|
|
e8671ed04e | ||
|
|
2044ae6b3a | ||
|
|
c683ec2bcb | ||
|
|
2e4e33156e | ||
|
|
04f4eeaca2 | ||
|
|
2e4b32204c | ||
|
|
34db13486a | ||
|
|
c6c6bb4041 | ||
|
|
a2ffb419c9 | ||
|
|
0127cec371 | ||
|
|
db3a6075f5 | ||
|
|
8876a15227 | ||
|
|
954eb40237 | ||
|
|
d4acdac168 | ||
|
|
817c7c445d | ||
|
|
da714a362b | ||
|
|
7b3941e5d4 | ||
|
|
15d8a40529 | ||
|
|
cdeaca73c4 | ||
|
|
bee22540a1 | ||
|
|
76880b84f9 | ||
|
|
2f0b57ca13 | ||
|
|
f90a022d3a | ||
|
|
f2fed21c11 | ||
|
|
d940974789 | ||
|
|
2a0d707ce1 | ||
|
|
aae9eea532 | ||
|
|
63b835f822 | ||
|
|
200b371d13 |
@@ -32,3 +32,6 @@ if [ ! -z "$DIFF" ]; then
|
||||
echo "$DIFF"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd src/android
|
||||
./gradlew ktlintCheck
|
||||
|
||||
@@ -8,17 +8,7 @@ variables:
|
||||
DisplayVersion: $[counter(variables['DisplayPrefix'], 1)]
|
||||
|
||||
stages:
|
||||
- stage: format
|
||||
displayName: 'format'
|
||||
jobs:
|
||||
- job: format
|
||||
displayName: 'clang'
|
||||
pool:
|
||||
vmImage: ubuntu-latest
|
||||
steps:
|
||||
- template: ./templates/format-check.yml
|
||||
- stage: build
|
||||
dependsOn: format
|
||||
displayName: 'build'
|
||||
jobs:
|
||||
- job: build
|
||||
@@ -43,7 +33,6 @@ stages:
|
||||
cache: 'true'
|
||||
version: $(DisplayVersion)
|
||||
- stage: build_win
|
||||
dependsOn: format
|
||||
displayName: 'build-windows'
|
||||
jobs:
|
||||
- job: build
|
||||
|
||||
8
.github/workflows/verify.yml
vendored
8
.github/workflows/verify.yml
vendored
@@ -13,13 +13,15 @@ jobs:
|
||||
format:
|
||||
name: 'verify format'
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: yuzuemu/build-environments:linux-clang-format
|
||||
options: -u 1001
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: false
|
||||
- name: set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
- name: 'Verify Formatting'
|
||||
run: bash -ex ./.ci/scripts/format/script.sh
|
||||
build:
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
| Pull Request | Commit | Title | Author | Merged? |
|
||||
|----|----|----|----|----|
|
||||
| [12579](https://github.com/yuzu-emu/yuzu-android//pull/12579) | [`66ae60a9e`](https://github.com/yuzu-emu/yuzu-android//pull/12579/files) | Core: Implement Device Mapping & GPU SMMU | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||
| [12610](https://github.com/yuzu-emu/yuzu-android//pull/12610) | [`200b371d1`](https://github.com/yuzu-emu/yuzu-android//pull/12610/files) | server_manager: respond to session close correctly | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12611](https://github.com/yuzu-emu/yuzu-android//pull/12611) | [`2f0b57ca1`](https://github.com/yuzu-emu/yuzu-android//pull/12611/files) | kernel: fix resource management issues | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12612](https://github.com/yuzu-emu/yuzu-android//pull/12612) | [`76880b84f`](https://github.com/yuzu-emu/yuzu-android//pull/12612/files) | fsp-srv: use program registry for SetCurrentProcess | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12652](https://github.com/yuzu-emu/yuzu-android//pull/12652) | [`2a0d707ce`](https://github.com/yuzu-emu/yuzu-android//pull/12652/files) | shader_recompiler: emulate 8-bit and 16-bit storage writes with cas loop | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12659](https://github.com/yuzu-emu/yuzu-android//pull/12659) | [`d94097478`](https://github.com/yuzu-emu/yuzu-android//pull/12659/files) | audio: fetch process object from handle table | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12579](https://github.com/yuzu-emu/yuzu-android//pull/12579) | [`93ef41f03`](https://github.com/yuzu-emu/yuzu-android//pull/12579/files) | Core: Implement Device Mapping & GPU SMMU | [FernandoS27](https://github.com/FernandoS27/) | Yes |
|
||||
| [12644](https://github.com/yuzu-emu/yuzu-android//pull/12644) | [`2044a289f`](https://github.com/yuzu-emu/yuzu-android//pull/12644/files) | shader_recompiler: fix Offset operand usage for non-OpImage*Gather | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
| [12688](https://github.com/yuzu-emu/yuzu-android//pull/12688) | [`e9eb017aa`](https://github.com/yuzu-emu/yuzu-android//pull/12688/files) | renderer_vulkan: recreate swapchain when frame size changes | [liamwhite](https://github.com/liamwhite/) | Yes |
|
||||
|
||||
|
||||
End of merge log. You can find the original README.md below the break.
|
||||
|
||||
@@ -188,8 +188,15 @@ tasks.create<Delete>("ktlintReset") {
|
||||
delete(File(buildDir.path + File.separator + "intermediates/ktLint"))
|
||||
}
|
||||
|
||||
val showFormatHelp = {
|
||||
logger.lifecycle(
|
||||
"If this check fails, please try running \"gradlew ktlintFormat\" for automatic " +
|
||||
"codestyle fixes"
|
||||
)
|
||||
}
|
||||
tasks.getByPath("ktlintKotlinScriptCheck").doFirst { showFormatHelp.invoke() }
|
||||
tasks.getByPath("ktlintMainSourceSetCheck").doFirst { showFormatHelp.invoke() }
|
||||
tasks.getByPath("loadKtlintReporters").dependsOn("ktlintReset")
|
||||
tasks.getByPath("preBuild").dependsOn("ktlintCheck")
|
||||
|
||||
ktlint {
|
||||
version.set("0.47.1")
|
||||
@@ -228,71 +235,33 @@ dependencies {
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
|
||||
}
|
||||
|
||||
fun getGitVersion(): String {
|
||||
var versionName = "0.0"
|
||||
|
||||
try {
|
||||
versionName = ProcessBuilder("git", "describe", "--always", "--long")
|
||||
fun runGitCommand(command: List<String>): String {
|
||||
return try {
|
||||
ProcessBuilder(command)
|
||||
.directory(project.rootDir)
|
||||
.redirectOutput(ProcessBuilder.Redirect.PIPE)
|
||||
.redirectError(ProcessBuilder.Redirect.PIPE)
|
||||
.start().inputStream.bufferedReader().use { it.readText() }
|
||||
.trim()
|
||||
} catch (e: Exception) {
|
||||
logger.error("Cannot find git")
|
||||
""
|
||||
}
|
||||
}
|
||||
|
||||
fun getGitVersion(): String {
|
||||
val versionName = if (System.getenv("GITHUB_ACTIONS") != null) {
|
||||
val gitTag = System.getenv("GIT_TAG_NAME") ?: ""
|
||||
gitTag
|
||||
} else {
|
||||
runGitCommand(listOf("git", "describe", "--always", "--long"))
|
||||
.replace(Regex("(-0)?-[^-]+$"), "")
|
||||
} catch (e: Exception) {
|
||||
logger.error("Cannot find git, defaulting to dummy version number")
|
||||
}
|
||||
|
||||
if (System.getenv("GITHUB_ACTIONS") != null) {
|
||||
val gitTag = System.getenv("GIT_TAG_NAME")
|
||||
versionName = gitTag ?: versionName
|
||||
}
|
||||
|
||||
return versionName
|
||||
return versionName.ifEmpty { "0.0" }
|
||||
}
|
||||
|
||||
fun getGitHash(): String {
|
||||
try {
|
||||
val processBuilder = ProcessBuilder("git", "rev-parse", "--short", "HEAD")
|
||||
processBuilder.directory(project.rootDir)
|
||||
val process = processBuilder.start()
|
||||
val inputStream = process.inputStream
|
||||
val errorStream = process.errorStream
|
||||
process.waitFor()
|
||||
fun getGitHash(): String =
|
||||
runGitCommand(listOf("git", "rev-parse", "--short", "HEAD")).ifEmpty { "dummy-hash" }
|
||||
|
||||
return if (process.exitValue() == 0) {
|
||||
inputStream.bufferedReader()
|
||||
.use { it.readText().trim() } // return the value of gitHash
|
||||
} else {
|
||||
val errorMessage = errorStream.bufferedReader().use { it.readText().trim() }
|
||||
logger.error("Error running git command: $errorMessage")
|
||||
"dummy-hash" // return a dummy hash value in case of an error
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("$e: Cannot find git, defaulting to dummy build hash")
|
||||
return "dummy-hash" // return a dummy hash value in case of an error
|
||||
}
|
||||
}
|
||||
|
||||
fun getBranch(): String {
|
||||
try {
|
||||
val processBuilder = ProcessBuilder("git", "rev-parse", "--abbrev-ref", "HEAD")
|
||||
processBuilder.directory(project.rootDir)
|
||||
val process = processBuilder.start()
|
||||
val inputStream = process.inputStream
|
||||
val errorStream = process.errorStream
|
||||
process.waitFor()
|
||||
|
||||
return if (process.exitValue() == 0) {
|
||||
inputStream.bufferedReader()
|
||||
.use { it.readText().trim() } // return the value of gitHash
|
||||
} else {
|
||||
val errorMessage = errorStream.bufferedReader().use { it.readText().trim() }
|
||||
logger.error("Error running git command: $errorMessage")
|
||||
"dummy-hash" // return a dummy hash value in case of an error
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.error("$e: Cannot find git, defaulting to dummy build hash")
|
||||
return "dummy-hash" // return a dummy hash value in case of an error
|
||||
}
|
||||
}
|
||||
fun getBranch(): String =
|
||||
runGitCommand(listOf("git", "rev-parse", "--abbrev-ref", "HEAD")).ifEmpty { "dummy-hash" }
|
||||
|
||||
@@ -76,8 +76,8 @@ class AboutFragment : Fragment() {
|
||||
binding.root.findNavController().navigate(R.id.action_aboutFragment_to_licensesFragment)
|
||||
}
|
||||
|
||||
binding.textBuildHash.text = BuildConfig.GIT_HASH
|
||||
binding.buttonBuildHash.setOnClickListener {
|
||||
binding.textVersionName.text = BuildConfig.VERSION_NAME
|
||||
binding.textVersionName.setOnClickListener {
|
||||
val clipBoard =
|
||||
requireContext().getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
|
||||
val clip = ClipData.newPlainText(getString(R.string.build), BuildConfig.GIT_HASH)
|
||||
|
||||
@@ -104,7 +104,7 @@ object FileUtil {
|
||||
|
||||
/**
|
||||
* Reference: https://stackoverflow.com/questions/42186820/documentfile-is-very-slow
|
||||
* This function will be faster than DoucmentFile.listFiles
|
||||
* This function will be faster than DocumentFile.listFiles
|
||||
* @param uri Directory uri.
|
||||
* @return CheapDocument lists.
|
||||
*/
|
||||
|
||||
@@ -21,7 +21,7 @@ void AndroidConfig::ReloadAllValues() {
|
||||
}
|
||||
|
||||
void AndroidConfig::SaveAllValues() {
|
||||
Save();
|
||||
SaveValues();
|
||||
SaveAndroidValues();
|
||||
}
|
||||
|
||||
|
||||
@@ -205,7 +205,7 @@ jboolean Java_org_yuzu_yuzu_1emu_utils_NativeConfig_getIsRuntimeModifiable(JNIEn
|
||||
jstring jkey) {
|
||||
auto setting = getSetting<std::string>(env, jkey);
|
||||
if (setting != nullptr) {
|
||||
return setting->RuntimeModfiable();
|
||||
return setting->RuntimeModifiable();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
android:layout_marginHorizontal="20dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_build_hash"
|
||||
android:id="@+id/button_version_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
@@ -164,7 +164,7 @@
|
||||
android:textAlignment="viewStart" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_build_hash"
|
||||
android:id="@+id/text_version_name"
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -148,7 +148,7 @@
|
||||
android:layout_marginHorizontal="20dp" />
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/button_build_hash"
|
||||
android:id="@+id/button_version_name"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingVertical="16dp"
|
||||
@@ -165,7 +165,7 @@
|
||||
android:text="@string/build" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/text_build_hash"
|
||||
android:id="@+id/text_version_name"
|
||||
style="@style/TextAppearance.Material3.BodyMedium"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
<item>@string/language_dutch</item>
|
||||
<item>@string/language_english</item>
|
||||
<item>@string/language_french</item>
|
||||
<item>@string/langauge_german</item>
|
||||
<item>@string/language_german</item>
|
||||
<item>@string/language_italian</item>
|
||||
<item>@string/language_japanese</item>
|
||||
<item>@string/language_korean</item>
|
||||
@@ -228,10 +228,10 @@
|
||||
<item>R</item>
|
||||
<item>ZL</item>
|
||||
<item>ZR</item>
|
||||
<item>@string/gamepad_left_stick</item>
|
||||
<item>@string/gamepad_right_stick</item>
|
||||
<item>L3</item>
|
||||
<item>R3</item>
|
||||
<item>@string/gamepad_left_stick</item>
|
||||
<item>@string/gamepad_right_stick</item>
|
||||
<item>@string/gamepad_d_pad</item>
|
||||
</string-array>
|
||||
|
||||
|
||||
@@ -410,7 +410,7 @@
|
||||
<string name="language_japanese" translatable="false">日本語</string>
|
||||
<string name="language_english" translatable="false">English</string>
|
||||
<string name="language_french" translatable="false">Français</string>
|
||||
<string name="langauge_german" translatable="false">Deutsch</string>
|
||||
<string name="language_german" translatable="false">Deutsch</string>
|
||||
<string name="language_italian" translatable="false">Italiano</string>
|
||||
<string name="language_spanish" translatable="false">Español</string>
|
||||
<string name="language_chinese" translatable="false">简体中文</string>
|
||||
|
||||
@@ -11,7 +11,7 @@ ADSP::ADSP(Core::System& system, Sink::Sink& sink) {
|
||||
opus_decoder = std::make_unique<OpusDecoder::OpusDecoder>(system);
|
||||
opus_decoder->Send(Direction::DSP, OpusDecoder::Message::Start);
|
||||
if (opus_decoder->Receive(Direction::Host) != OpusDecoder::Message::StartOK) {
|
||||
LOG_ERROR(Service_Audio, "OpusDeocder failed to initialize.");
|
||||
LOG_ERROR(Service_Audio, "OpusDecoder failed to initialize.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info,
|
||||
const VoiceState& voice_state, const s8 channel) {
|
||||
if (voice_info.mix_id == UnusedMixId) {
|
||||
if (voice_info.splitter_id != UnusedSplitterId) {
|
||||
auto destination{splitter_context.GetDesintationData(voice_info.splitter_id, 0)};
|
||||
auto destination{splitter_context.GetDestinationData(voice_info.splitter_id, 0)};
|
||||
u32 dest_id{0};
|
||||
while (destination != nullptr) {
|
||||
if (destination->IsConfigured()) {
|
||||
@@ -55,7 +55,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info,
|
||||
}
|
||||
}
|
||||
dest_id++;
|
||||
destination = splitter_context.GetDesintationData(voice_info.splitter_id, dest_id);
|
||||
destination = splitter_context.GetDestinationData(voice_info.splitter_id, dest_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -234,7 +234,7 @@ void CommandGenerator::GenerateVoiceCommand(VoiceInfo& voice_info) {
|
||||
if (voice_info.mix_id == UnusedMixId) {
|
||||
if (voice_info.splitter_id != UnusedSplitterId) {
|
||||
auto i{channel};
|
||||
auto destination{splitter_context.GetDesintationData(voice_info.splitter_id, i)};
|
||||
auto destination{splitter_context.GetDestinationData(voice_info.splitter_id, i)};
|
||||
while (destination != nullptr) {
|
||||
if (destination->IsConfigured()) {
|
||||
const auto mix_id{destination->GetMixId()};
|
||||
@@ -249,7 +249,7 @@ void CommandGenerator::GenerateVoiceCommand(VoiceInfo& voice_info) {
|
||||
}
|
||||
}
|
||||
i += voice_info.channel_count;
|
||||
destination = splitter_context.GetDesintationData(voice_info.splitter_id, i);
|
||||
destination = splitter_context.GetDestinationData(voice_info.splitter_id, i);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@@ -591,7 +591,7 @@ void CommandGenerator::GenerateMixCommands(MixInfo& mix_info) {
|
||||
if (mix_info.dst_splitter_id != UnusedSplitterId) {
|
||||
s16 dest_id{0};
|
||||
auto destination{
|
||||
splitter_context.GetDesintationData(mix_info.dst_splitter_id, dest_id)};
|
||||
splitter_context.GetDestinationData(mix_info.dst_splitter_id, dest_id)};
|
||||
while (destination != nullptr) {
|
||||
if (destination->IsConfigured()) {
|
||||
auto splitter_mix_id{destination->GetMixId()};
|
||||
@@ -612,7 +612,7 @@ void CommandGenerator::GenerateMixCommands(MixInfo& mix_info) {
|
||||
}
|
||||
dest_id++;
|
||||
destination =
|
||||
splitter_context.GetDesintationData(mix_info.dst_splitter_id, dest_id);
|
||||
splitter_context.GetDestinationData(mix_info.dst_splitter_id, dest_id);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -93,7 +93,7 @@ bool MixInfo::UpdateConnection(EdgeMatrix& edge_matrix, const InParameter& in_pa
|
||||
|
||||
for (u32 i = 0; i < destination_count; i++) {
|
||||
auto destination{
|
||||
splitter_context.GetDesintationData(in_params.dest_splitter_id, i)};
|
||||
splitter_context.GetDestinationData(in_params.dest_splitter_id, i)};
|
||||
|
||||
if (destination) {
|
||||
const auto destination_id{destination->GetMixId()};
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
namespace AudioCore::Renderer {
|
||||
|
||||
SplitterDestinationData* SplitterContext::GetDesintationData(const s32 splitter_id,
|
||||
SplitterDestinationData* SplitterContext::GetDestinationData(const s32 splitter_id,
|
||||
const s32 destination_id) {
|
||||
return splitter_infos[splitter_id].GetData(destination_id);
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ public:
|
||||
* @param destination_id - Destination index within the splitter.
|
||||
* @return Pointer to the found destination. May be nullptr.
|
||||
*/
|
||||
SplitterDestinationData* GetDesintationData(s32 splitter_id, s32 destination_id);
|
||||
SplitterDestinationData* GetDestinationData(s32 splitter_id, s32 destination_id);
|
||||
|
||||
/**
|
||||
* Get a splitter from the given index.
|
||||
|
||||
@@ -35,7 +35,7 @@ bool BasicSetting::Save() const {
|
||||
return save;
|
||||
}
|
||||
|
||||
bool BasicSetting::RuntimeModfiable() const {
|
||||
bool BasicSetting::RuntimeModifiable() const {
|
||||
return runtime_modifiable;
|
||||
}
|
||||
|
||||
|
||||
@@ -186,7 +186,7 @@ public:
|
||||
/**
|
||||
* @returns true if the current setting can be changed while the guest is running.
|
||||
*/
|
||||
[[nodiscard]] bool RuntimeModfiable() const;
|
||||
[[nodiscard]] bool RuntimeModifiable() const;
|
||||
|
||||
/**
|
||||
* @returns A unique number corresponding to the setting.
|
||||
|
||||
@@ -22,14 +22,10 @@ using NativeExecutionParameters = Kernel::KThread::NativeExecutionParameters;
|
||||
constexpr size_t MaxRelativeBranch = 128_MiB;
|
||||
constexpr u32 ModuleCodeIndex = 0x24 / sizeof(u32);
|
||||
|
||||
Patcher::Patcher() : c(m_patch_instructions) {}
|
||||
|
||||
Patcher::~Patcher() = default;
|
||||
|
||||
void Patcher::PatchText(const Kernel::PhysicalMemory& program_image,
|
||||
const Kernel::CodeSet::Segment& code) {
|
||||
// Branch to the first instruction of the module.
|
||||
this->BranchToModule(0);
|
||||
Patcher::Patcher() : c(m_patch_instructions) {
|
||||
// The first word of the patch section is always a branch to the first instruction of the
|
||||
// module.
|
||||
c.dw(0);
|
||||
|
||||
// Write save context helper function.
|
||||
c.l(m_save_context);
|
||||
@@ -38,6 +34,25 @@ void Patcher::PatchText(const Kernel::PhysicalMemory& program_image,
|
||||
// Write load context helper function.
|
||||
c.l(m_load_context);
|
||||
WriteLoadContext();
|
||||
}
|
||||
|
||||
Patcher::~Patcher() = default;
|
||||
|
||||
bool Patcher::PatchText(const Kernel::PhysicalMemory& program_image,
|
||||
const Kernel::CodeSet::Segment& code) {
|
||||
// If we have patched modules but cannot reach the new module, then it needs its own patcher.
|
||||
const size_t image_size = program_image.size();
|
||||
if (total_program_size + image_size > MaxRelativeBranch && total_program_size > 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Add a new module patch to our list
|
||||
modules.emplace_back();
|
||||
curr_patch = &modules.back();
|
||||
|
||||
// The first word of the patch section is always a branch to the first instruction of the
|
||||
// module.
|
||||
curr_patch->m_branch_to_module_relocations.push_back({0, 0});
|
||||
|
||||
// Retrieve text segment data.
|
||||
const auto text = std::span{program_image}.subspan(code.offset, code.size);
|
||||
@@ -94,16 +109,17 @@ void Patcher::PatchText(const Kernel::PhysicalMemory& program_image,
|
||||
}
|
||||
|
||||
if (auto exclusive = Exclusive{inst}; exclusive.Verify()) {
|
||||
m_exclusives.push_back(i);
|
||||
curr_patch->m_exclusives.push_back(i);
|
||||
}
|
||||
}
|
||||
|
||||
// Determine patching mode for the final relocation step
|
||||
const size_t image_size = program_image.size();
|
||||
total_program_size += image_size;
|
||||
this->mode = image_size > MaxRelativeBranch ? PatchMode::PreText : PatchMode::PostData;
|
||||
return true;
|
||||
}
|
||||
|
||||
void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||
bool Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||
const Kernel::CodeSet::Segment& code,
|
||||
Kernel::PhysicalMemory& program_image,
|
||||
EntryTrampolines* out_trampolines) {
|
||||
@@ -120,7 +136,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||
if (mode == PatchMode::PreText) {
|
||||
rc.B(rel.patch_offset - patch_size - rel.module_offset);
|
||||
} else {
|
||||
rc.B(image_size - rel.module_offset + rel.patch_offset);
|
||||
rc.B(total_program_size - rel.module_offset + rel.patch_offset);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -129,7 +145,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||
if (mode == PatchMode::PreText) {
|
||||
rc.B(patch_size - rel.patch_offset + rel.module_offset);
|
||||
} else {
|
||||
rc.B(rel.module_offset - image_size - rel.patch_offset);
|
||||
rc.B(rel.module_offset - total_program_size - rel.patch_offset);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -137,7 +153,7 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||
if (mode == PatchMode::PreText) {
|
||||
return GetInteger(load_base) + patch_offset;
|
||||
} else {
|
||||
return GetInteger(load_base) + image_size + patch_offset;
|
||||
return GetInteger(load_base) + total_program_size + patch_offset;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -150,39 +166,50 @@ void Patcher::RelocateAndCopy(Common::ProcessAddress load_base,
|
||||
};
|
||||
|
||||
// We are now ready to relocate!
|
||||
for (const Relocation& rel : m_branch_to_patch_relocations) {
|
||||
auto& patch = modules[m_relocate_module_index++];
|
||||
for (const Relocation& rel : patch.m_branch_to_patch_relocations) {
|
||||
ApplyBranchToPatchRelocation(text_words.data() + rel.module_offset / sizeof(u32), rel);
|
||||
}
|
||||
for (const Relocation& rel : m_branch_to_module_relocations) {
|
||||
for (const Relocation& rel : patch.m_branch_to_module_relocations) {
|
||||
ApplyBranchToModuleRelocation(m_patch_instructions.data() + rel.patch_offset / sizeof(u32),
|
||||
rel);
|
||||
}
|
||||
|
||||
// Rewrite PC constants and record post trampolines
|
||||
for (const Relocation& rel : m_write_module_pc_relocations) {
|
||||
for (const Relocation& rel : patch.m_write_module_pc_relocations) {
|
||||
oaknut::CodeGenerator rc{m_patch_instructions.data() + rel.patch_offset / sizeof(u32)};
|
||||
rc.dx(RebasePc(rel.module_offset));
|
||||
}
|
||||
for (const Trampoline& rel : m_trampolines) {
|
||||
for (const Trampoline& rel : patch.m_trampolines) {
|
||||
out_trampolines->insert({RebasePc(rel.module_offset), RebasePatch(rel.patch_offset)});
|
||||
}
|
||||
|
||||
// Cortex-A57 seems to treat all exclusives as ordered, but newer processors do not.
|
||||
// Convert to ordered to preserve this assumption.
|
||||
for (const ModuleTextAddress i : m_exclusives) {
|
||||
for (const ModuleTextAddress i : patch.m_exclusives) {
|
||||
auto exclusive = Exclusive{text_words[i]};
|
||||
text_words[i] = exclusive.AsOrdered();
|
||||
}
|
||||
|
||||
// Copy to program image
|
||||
if (this->mode == PatchMode::PreText) {
|
||||
std::memcpy(program_image.data(), m_patch_instructions.data(),
|
||||
m_patch_instructions.size() * sizeof(u32));
|
||||
} else {
|
||||
program_image.resize(image_size + patch_size);
|
||||
std::memcpy(program_image.data() + image_size, m_patch_instructions.data(),
|
||||
m_patch_instructions.size() * sizeof(u32));
|
||||
// Remove the patched module size from the total. This is done so total_program_size
|
||||
// always represents the distance from the currently patched module to the patch section.
|
||||
total_program_size -= image_size;
|
||||
|
||||
// Only copy to the program image of the last module
|
||||
if (m_relocate_module_index == modules.size()) {
|
||||
if (this->mode == PatchMode::PreText) {
|
||||
ASSERT(image_size == total_program_size);
|
||||
std::memcpy(program_image.data(), m_patch_instructions.data(),
|
||||
m_patch_instructions.size() * sizeof(u32));
|
||||
} else {
|
||||
program_image.resize(image_size + patch_size);
|
||||
std::memcpy(program_image.data() + image_size, m_patch_instructions.data(),
|
||||
m_patch_instructions.size() * sizeof(u32));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t Patcher::GetSectionSize() const noexcept {
|
||||
@@ -322,7 +349,7 @@ void Patcher::WriteSvcTrampoline(ModuleDestLabel module_dest, u32 svc_id) {
|
||||
|
||||
// Write the post-SVC trampoline address, which will jump back to the guest after restoring its
|
||||
// state.
|
||||
m_trampolines.push_back({c.offset(), module_dest});
|
||||
curr_patch->m_trampolines.push_back({c.offset(), module_dest});
|
||||
|
||||
// Host called this location. Save the return address so we can
|
||||
// unwind the stack properly when jumping back.
|
||||
|
||||
@@ -31,9 +31,9 @@ public:
|
||||
explicit Patcher();
|
||||
~Patcher();
|
||||
|
||||
void PatchText(const Kernel::PhysicalMemory& program_image,
|
||||
bool PatchText(const Kernel::PhysicalMemory& program_image,
|
||||
const Kernel::CodeSet::Segment& code);
|
||||
void RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
||||
bool RelocateAndCopy(Common::ProcessAddress load_base, const Kernel::CodeSet::Segment& code,
|
||||
Kernel::PhysicalMemory& program_image, EntryTrampolines* out_trampolines);
|
||||
size_t GetSectionSize() const noexcept;
|
||||
|
||||
@@ -61,16 +61,16 @@ private:
|
||||
|
||||
private:
|
||||
void BranchToPatch(uintptr_t module_dest) {
|
||||
m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
||||
curr_patch->m_branch_to_patch_relocations.push_back({c.offset(), module_dest});
|
||||
}
|
||||
|
||||
void BranchToModule(uintptr_t module_dest) {
|
||||
m_branch_to_module_relocations.push_back({c.offset(), module_dest});
|
||||
curr_patch->m_branch_to_module_relocations.push_back({c.offset(), module_dest});
|
||||
c.dw(0);
|
||||
}
|
||||
|
||||
void WriteModulePc(uintptr_t module_dest) {
|
||||
m_write_module_pc_relocations.push_back({c.offset(), module_dest});
|
||||
curr_patch->m_write_module_pc_relocations.push_back({c.offset(), module_dest});
|
||||
c.dx(0);
|
||||
}
|
||||
|
||||
@@ -84,15 +84,22 @@ private:
|
||||
uintptr_t module_offset; ///< Offset in bytes from the start of the text section.
|
||||
};
|
||||
|
||||
struct ModulePatch {
|
||||
std::vector<Trampoline> m_trampolines;
|
||||
std::vector<Relocation> m_branch_to_patch_relocations{};
|
||||
std::vector<Relocation> m_branch_to_module_relocations{};
|
||||
std::vector<Relocation> m_write_module_pc_relocations{};
|
||||
std::vector<ModuleTextAddress> m_exclusives{};
|
||||
};
|
||||
|
||||
oaknut::VectorCodeGenerator c;
|
||||
std::vector<Trampoline> m_trampolines;
|
||||
std::vector<Relocation> m_branch_to_patch_relocations{};
|
||||
std::vector<Relocation> m_branch_to_module_relocations{};
|
||||
std::vector<Relocation> m_write_module_pc_relocations{};
|
||||
std::vector<ModuleTextAddress> m_exclusives{};
|
||||
oaknut::Label m_save_context{};
|
||||
oaknut::Label m_load_context{};
|
||||
PatchMode mode{PatchMode::None};
|
||||
size_t total_program_size{};
|
||||
size_t m_relocate_module_index{};
|
||||
std::vector<ModulePatch> modules;
|
||||
ModulePatch* curr_patch;
|
||||
};
|
||||
|
||||
} // namespace Core::NCE
|
||||
|
||||
@@ -28,6 +28,10 @@ class Memory;
|
||||
template <typename DTraits>
|
||||
struct DeviceMemoryManagerAllocator;
|
||||
|
||||
struct Asid {
|
||||
size_t id;
|
||||
};
|
||||
|
||||
template <typename Traits>
|
||||
class DeviceMemoryManager {
|
||||
using DeviceInterface = typename Traits::DeviceInterface;
|
||||
@@ -43,15 +47,14 @@ public:
|
||||
void AllocateFixed(DAddr start, size_t size);
|
||||
void Free(DAddr start, size_t size);
|
||||
|
||||
void Map(DAddr address, VAddr virtual_address, size_t size, size_t process_id,
|
||||
bool track = false);
|
||||
void Map(DAddr address, VAddr virtual_address, size_t size, Asid asid, bool track = false);
|
||||
|
||||
void Unmap(DAddr address, size_t size);
|
||||
|
||||
void TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, size_t process_id);
|
||||
void TrackContinuity(DAddr address, VAddr virtual_address, size_t size, size_t process_id) {
|
||||
void TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, Asid asid);
|
||||
void TrackContinuity(DAddr address, VAddr virtual_address, size_t size, Asid asid) {
|
||||
std::scoped_lock lk(mapping_guard);
|
||||
TrackContinuityImpl(address, virtual_address, size, process_id);
|
||||
TrackContinuityImpl(address, virtual_address, size, asid);
|
||||
}
|
||||
|
||||
// Write / Read
|
||||
@@ -105,8 +108,8 @@ public:
|
||||
void WriteBlock(DAddr address, const void* src_pointer, size_t size);
|
||||
void WriteBlockUnsafe(DAddr address, const void* src_pointer, size_t size);
|
||||
|
||||
size_t RegisterProcess(Memory::Memory* memory);
|
||||
void UnregisterProcess(size_t id);
|
||||
Asid RegisterProcess(Memory::Memory* memory);
|
||||
void UnregisterProcess(Asid id);
|
||||
|
||||
void UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta);
|
||||
|
||||
@@ -163,17 +166,17 @@ private:
|
||||
static constexpr size_t guest_max_as_bits = 39;
|
||||
static constexpr size_t guest_as_size = 1ULL << guest_max_as_bits;
|
||||
static constexpr size_t guest_mask = guest_as_size - 1ULL;
|
||||
static constexpr size_t process_id_start_bit = guest_max_as_bits;
|
||||
static constexpr size_t asid_start_bit = guest_max_as_bits;
|
||||
|
||||
std::pair<size_t, VAddr> ExtractCPUBacking(size_t page_index) {
|
||||
std::pair<Asid, VAddr> ExtractCPUBacking(size_t page_index) {
|
||||
auto content = cpu_backing_address[page_index];
|
||||
const VAddr address = content & guest_mask;
|
||||
const size_t process_id = static_cast<size_t>(content >> process_id_start_bit);
|
||||
return std::make_pair(process_id, address);
|
||||
const Asid asid{static_cast<size_t>(content >> asid_start_bit)};
|
||||
return std::make_pair(asid, address);
|
||||
}
|
||||
|
||||
void InsertCPUBacking(size_t page_index, VAddr address, size_t process_id) {
|
||||
cpu_backing_address[page_index] = address | (process_id << process_id_start_bit);
|
||||
void InsertCPUBacking(size_t page_index, VAddr address, Asid asid) {
|
||||
cpu_backing_address[page_index] = address | (asid.id << asid_start_bit);
|
||||
}
|
||||
|
||||
Common::VirtualBuffer<VAddr> cpu_backing_address;
|
||||
@@ -205,4 +208,4 @@ private:
|
||||
std::mutex mapping_guard;
|
||||
};
|
||||
|
||||
} // namespace Core
|
||||
} // namespace Core
|
||||
|
||||
@@ -215,8 +215,8 @@ void DeviceMemoryManager<Traits>::Free(DAddr start, size_t size) {
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size_t size,
|
||||
size_t process_id, bool track) {
|
||||
Core::Memory::Memory* process_memory = registered_processes[process_id];
|
||||
Asid asid, bool track) {
|
||||
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||
std::scoped_lock lk(mapping_guard);
|
||||
@@ -229,7 +229,7 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
|
||||
}
|
||||
auto phys_addr = static_cast<u32>(GetRawPhysicalAddr(ptr) >> Memory::YUZU_PAGEBITS) + 1U;
|
||||
compressed_physical_ptr[start_page_d + i] = phys_addr;
|
||||
InsertCPUBacking(start_page_d + i, new_vaddress, process_id);
|
||||
InsertCPUBacking(start_page_d + i, new_vaddress, asid);
|
||||
const u32 base_dev = compressed_device_addr[phys_addr - 1U];
|
||||
const u32 new_dev = static_cast<u32>(start_page_d + i);
|
||||
if (base_dev == 0) [[likely]] {
|
||||
@@ -244,7 +244,7 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size
|
||||
impl->multi_dev_address.Register(new_dev, start_id);
|
||||
}
|
||||
if (track) {
|
||||
TrackContinuityImpl(address, virtual_address, size, process_id);
|
||||
TrackContinuityImpl(address, virtual_address, size, asid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,8 +277,8 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) {
|
||||
}
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address,
|
||||
size_t size, size_t process_id) {
|
||||
Core::Memory::Memory* process_memory = registered_processes[process_id];
|
||||
size_t size, Asid asid) {
|
||||
Core::Memory::Memory* process_memory = registered_processes[asid.id];
|
||||
size_t start_page_d = address >> Memory::YUZU_PAGEBITS;
|
||||
size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS;
|
||||
uintptr_t last_ptr = 0;
|
||||
@@ -488,8 +488,8 @@ void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* sr
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
size_t DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_device_inter) {
|
||||
size_t new_id;
|
||||
Asid DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_device_inter) {
|
||||
size_t new_id{};
|
||||
if (!id_pool.empty()) {
|
||||
new_id = id_pool.front();
|
||||
id_pool.pop_front();
|
||||
@@ -498,29 +498,23 @@ size_t DeviceMemoryManager<Traits>::RegisterProcess(Memory::Memory* memory_devic
|
||||
registered_processes.emplace_back(memory_device_inter);
|
||||
new_id = registered_processes.size() - 1U;
|
||||
}
|
||||
return new_id;
|
||||
return Asid{new_id};
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::UnregisterProcess(size_t id) {
|
||||
registered_processes[id] = nullptr;
|
||||
id_pool.push_front(id);
|
||||
void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
|
||||
registered_processes[asid.id] = nullptr;
|
||||
id_pool.push_front(asid.id);
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
|
||||
bool locked = false;
|
||||
auto lock = [&] {
|
||||
if (!locked) {
|
||||
counter_guard.lock();
|
||||
locked = true;
|
||||
std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock);
|
||||
const auto Lock = [&] {
|
||||
if (!lk) {
|
||||
lk.lock();
|
||||
}
|
||||
};
|
||||
SCOPE_EXIT({
|
||||
if (locked) {
|
||||
counter_guard.unlock();
|
||||
}
|
||||
});
|
||||
u64 uncache_begin = 0;
|
||||
u64 cache_begin = 0;
|
||||
u64 uncache_bytes = 0;
|
||||
@@ -530,9 +524,9 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
const size_t page_end = Common::DivCeil(addr + size, Memory::YUZU_PAGESIZE);
|
||||
size_t page = addr >> Memory::YUZU_PAGEBITS;
|
||||
auto [process_id, base_vaddress] = ExtractCPUBacking(page);
|
||||
auto [asid, base_vaddress] = ExtractCPUBacking(page);
|
||||
size_t vpage = base_vaddress >> Memory::YUZU_PAGEBITS;
|
||||
auto* memory_device_inter = registered_processes[process_id];
|
||||
auto* memory_device_inter = registered_processes[asid.id];
|
||||
for (; page != page_end; ++page) {
|
||||
std::atomic_uint8_t& count = cached_pages->at(page >> 3).Count(page);
|
||||
|
||||
@@ -555,7 +549,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
}
|
||||
uncache_bytes += Memory::YUZU_PAGESIZE;
|
||||
} else if (uncache_bytes > 0) {
|
||||
lock();
|
||||
Lock();
|
||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
|
||||
uncache_bytes, false);
|
||||
uncache_bytes = 0;
|
||||
@@ -566,7 +560,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
}
|
||||
cache_bytes += Memory::YUZU_PAGESIZE;
|
||||
} else if (cache_bytes > 0) {
|
||||
lock();
|
||||
Lock();
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||
true);
|
||||
cache_bytes = 0;
|
||||
@@ -574,12 +568,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
|
||||
vpage++;
|
||||
}
|
||||
if (uncache_bytes > 0) {
|
||||
lock();
|
||||
Lock();
|
||||
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
|
||||
false);
|
||||
}
|
||||
if (cache_bytes > 0) {
|
||||
lock();
|
||||
Lock();
|
||||
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
|
||||
true);
|
||||
}
|
||||
|
||||
@@ -1239,10 +1239,10 @@ void KProcess::LoadModule(CodeSet code_set, KProcessAddress base_addr) {
|
||||
ReprotectSegment(code_set.DataSegment(), Svc::MemoryPermission::ReadWrite);
|
||||
|
||||
#ifdef HAS_NCE
|
||||
if (this->IsApplication() && Settings::IsNceEnabled()) {
|
||||
const auto& patch = code_set.PatchSegment();
|
||||
if (this->IsApplication() && Settings::IsNceEnabled() && patch.size != 0) {
|
||||
auto& buffer = m_kernel.System().DeviceMemory().buffer;
|
||||
const auto& code = code_set.CodeSegment();
|
||||
const auto& patch = code_set.PatchSegment();
|
||||
buffer.Protect(GetInteger(base_addr + code.addr), code.size,
|
||||
Common::MemoryPermission::Read | Common::MemoryPermission::Execute);
|
||||
buffer.Protect(GetInteger(base_addr + patch.addr), patch.size,
|
||||
|
||||
@@ -61,9 +61,7 @@ ProfileManager::ProfileManager() {
|
||||
OpenUser(*GetUser(current));
|
||||
}
|
||||
|
||||
ProfileManager::~ProfileManager() {
|
||||
WriteUserSaveFile();
|
||||
}
|
||||
ProfileManager::~ProfileManager() = default;
|
||||
|
||||
/// After a users creation it needs to be "registered" to the system. AddToProfiles handles the
|
||||
/// internal management of the users profiles
|
||||
@@ -113,6 +111,8 @@ Result ProfileManager::CreateNewUser(UUID uuid, const ProfileUsername& username)
|
||||
return ERROR_USER_ALREADY_EXISTS;
|
||||
}
|
||||
|
||||
is_save_needed = true;
|
||||
|
||||
return AddUser({
|
||||
.user_uuid = uuid,
|
||||
.username = username,
|
||||
@@ -326,6 +326,9 @@ bool ProfileManager::RemoveUser(UUID uuid) {
|
||||
profiles[*index] = ProfileInfo{};
|
||||
std::stable_partition(profiles.begin(), profiles.end(),
|
||||
[](const ProfileInfo& profile) { return profile.user_uuid.IsValid(); });
|
||||
|
||||
is_save_needed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -340,6 +343,8 @@ bool ProfileManager::SetProfileBase(UUID uuid, const ProfileBase& profile_new) {
|
||||
profile.username = profile_new.username;
|
||||
profile.creation_time = profile_new.timestamp;
|
||||
|
||||
is_save_needed = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -348,6 +353,7 @@ bool ProfileManager::SetProfileBaseAndData(Common::UUID uuid, const ProfileBase&
|
||||
const auto index = GetUserIndex(uuid);
|
||||
if (index.has_value() && SetProfileBase(uuid, profile_new)) {
|
||||
profiles[*index].data = data_new;
|
||||
is_save_needed = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -391,6 +397,10 @@ void ProfileManager::ParseUserSaveFile() {
|
||||
}
|
||||
|
||||
void ProfileManager::WriteUserSaveFile() {
|
||||
if (!is_save_needed) {
|
||||
return;
|
||||
}
|
||||
|
||||
ProfileDataRaw raw{};
|
||||
|
||||
for (std::size_t i = 0; i < MAX_USERS; ++i) {
|
||||
@@ -423,7 +433,10 @@ void ProfileManager::WriteUserSaveFile() {
|
||||
if (!save.IsOpen() || !save.SetSize(sizeof(ProfileDataRaw)) || !save.WriteObject(raw)) {
|
||||
LOG_WARNING(Service_ACC, "Failed to write save data to file... No changes to user data "
|
||||
"made in current session will be saved.");
|
||||
return;
|
||||
}
|
||||
|
||||
is_save_needed = false;
|
||||
}
|
||||
|
||||
}; // namespace Service::Account
|
||||
|
||||
@@ -103,6 +103,7 @@ private:
|
||||
std::optional<std::size_t> AddToProfiles(const ProfileInfo& profile);
|
||||
bool RemoveProfileAtIndex(std::size_t index);
|
||||
|
||||
bool is_save_needed{};
|
||||
std::array<ProfileInfo, MAX_USERS> profiles{};
|
||||
std::array<ProfileInfo, MAX_USERS> stored_opened_profiles{};
|
||||
std::size_t user_count{};
|
||||
|
||||
@@ -16,9 +16,8 @@
|
||||
|
||||
namespace Service::Nvidia::NvCore {
|
||||
|
||||
Session::Session(size_t id_, Kernel::KProcess* process_, size_t smmu_id_)
|
||||
: id{id_}, process{process_}, smmu_id{smmu_id_},
|
||||
has_preallocated_area{}, mapper{}, is_active{} {}
|
||||
Session::Session(SessionId id_, Kernel::KProcess* process_, Core::Asid asid_)
|
||||
: id{id_}, process{process_}, asid{asid_}, has_preallocated_area{}, mapper{}, is_active{} {}
|
||||
|
||||
Session::~Session() = default;
|
||||
|
||||
@@ -41,7 +40,9 @@ Container::Container(Tegra::Host1x::Host1x& host1x_) {
|
||||
|
||||
Container::~Container() = default;
|
||||
|
||||
size_t Container::OpenSession(Kernel::KProcess* process) {
|
||||
SessionId Container::OpenSession(Kernel::KProcess* process) {
|
||||
using namespace Common::Literals;
|
||||
|
||||
std::scoped_lock lk(impl->session_guard);
|
||||
for (auto& session : impl->sessions) {
|
||||
if (!session.is_active) {
|
||||
@@ -54,14 +55,14 @@ size_t Container::OpenSession(Kernel::KProcess* process) {
|
||||
size_t new_id{};
|
||||
auto* memory_interface = &process->GetMemory();
|
||||
auto& smmu = impl->host1x.MemoryManager();
|
||||
auto smmu_id = smmu.RegisterProcess(memory_interface);
|
||||
auto asid = smmu.RegisterProcess(memory_interface);
|
||||
if (!impl->id_pool.empty()) {
|
||||
new_id = impl->id_pool.front();
|
||||
impl->id_pool.pop_front();
|
||||
impl->sessions[new_id] = Session{new_id, process, smmu_id};
|
||||
impl->sessions[new_id] = Session{SessionId{new_id}, process, asid};
|
||||
} else {
|
||||
new_id = impl->new_ids++;
|
||||
impl->sessions.emplace_back(new_id, process, smmu_id);
|
||||
impl->sessions.emplace_back(SessionId{new_id}, process, asid);
|
||||
}
|
||||
auto& session = impl->sessions[new_id];
|
||||
session.is_active = true;
|
||||
@@ -80,7 +81,7 @@ size_t Container::OpenSession(Kernel::KProcess* process) {
|
||||
cur_addr));
|
||||
auto svc_mem_info = mem_info.GetSvcMemoryInfo();
|
||||
|
||||
// check if this memory block is heap
|
||||
// Check if this memory block is heap.
|
||||
if (svc_mem_info.state == Kernel::Svc::MemoryState::Normal) {
|
||||
if (svc_mem_info.size > region_size) {
|
||||
region_size = svc_mem_info.size;
|
||||
@@ -97,21 +98,21 @@ size_t Container::OpenSession(Kernel::KProcess* process) {
|
||||
cur_addr = next_address;
|
||||
}
|
||||
session.has_preallocated_area = false;
|
||||
auto start_region = (region_size >> 15) >= 1024 ? smmu.Allocate(region_size) : 0;
|
||||
auto start_region = region_size >= 32_MiB ? smmu.Allocate(region_size) : 0;
|
||||
if (start_region != 0) {
|
||||
session.mapper = std::make_unique<HeapMapper>(region_start, start_region, region_size,
|
||||
smmu_id, impl->host1x);
|
||||
smmu.TrackContinuity(start_region, region_start, region_size, smmu_id);
|
||||
asid, impl->host1x);
|
||||
smmu.TrackContinuity(start_region, region_start, region_size, asid);
|
||||
session.has_preallocated_area = true;
|
||||
LOG_CRITICAL(Debug, "Preallocation created!");
|
||||
LOG_DEBUG(Debug, "Preallocation created!");
|
||||
}
|
||||
}
|
||||
return new_id;
|
||||
return SessionId{new_id};
|
||||
}
|
||||
|
||||
void Container::CloseSession(size_t id) {
|
||||
void Container::CloseSession(SessionId session_id) {
|
||||
std::scoped_lock lk(impl->session_guard);
|
||||
auto& session = impl->sessions[id];
|
||||
auto& session = impl->sessions[session_id.id];
|
||||
auto& smmu = impl->host1x.MemoryManager();
|
||||
if (session.has_preallocated_area) {
|
||||
const DAddr region_start = session.mapper->GetRegionStart();
|
||||
@@ -121,13 +122,13 @@ void Container::CloseSession(size_t id) {
|
||||
session.has_preallocated_area = false;
|
||||
}
|
||||
session.is_active = false;
|
||||
smmu.UnregisterProcess(impl->sessions[id].smmu_id);
|
||||
impl->id_pool.emplace_front(id);
|
||||
smmu.UnregisterProcess(impl->sessions[session_id.id].asid);
|
||||
impl->id_pool.emplace_front(session_id.id);
|
||||
}
|
||||
|
||||
Session* Container::GetSession(size_t id) {
|
||||
Session* Container::GetSession(SessionId session_id) {
|
||||
std::atomic_thread_fence(std::memory_order_acquire);
|
||||
return &impl->sessions[id];
|
||||
return &impl->sessions[session_id.id];
|
||||
}
|
||||
|
||||
NvMap& Container::GetNvMapFile() {
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "core/device_memory_manager.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
|
||||
namespace Kernel {
|
||||
@@ -26,8 +27,12 @@ class SyncpointManager;
|
||||
|
||||
struct ContainerImpl;
|
||||
|
||||
struct SessionId {
|
||||
size_t id;
|
||||
};
|
||||
|
||||
struct Session {
|
||||
Session(size_t id_, Kernel::KProcess* process_, size_t smmu_id_);
|
||||
Session(SessionId id_, Kernel::KProcess* process_, Core::Asid asid_);
|
||||
~Session();
|
||||
|
||||
Session(const Session&) = delete;
|
||||
@@ -35,9 +40,9 @@ struct Session {
|
||||
Session(Session&&) = default;
|
||||
Session& operator=(Session&&) = default;
|
||||
|
||||
size_t id;
|
||||
SessionId id;
|
||||
Kernel::KProcess* process;
|
||||
size_t smmu_id;
|
||||
Core::Asid asid;
|
||||
bool has_preallocated_area{};
|
||||
std::unique_ptr<HeapMapper> mapper{};
|
||||
bool is_active{};
|
||||
@@ -48,10 +53,10 @@ public:
|
||||
explicit Container(Tegra::Host1x::Host1x& host1x);
|
||||
~Container();
|
||||
|
||||
size_t OpenSession(Kernel::KProcess* process);
|
||||
void CloseSession(size_t id);
|
||||
SessionId OpenSession(Kernel::KProcess* process);
|
||||
void CloseSession(SessionId id);
|
||||
|
||||
Session* GetSession(size_t id);
|
||||
Session* GetSession(SessionId id);
|
||||
|
||||
NvMap& GetNvMapFile();
|
||||
|
||||
|
||||
@@ -109,9 +109,9 @@ struct HeapMapper::HeapMapperInternal {
|
||||
std::mutex guard;
|
||||
};
|
||||
|
||||
HeapMapper::HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, size_t smmu_id,
|
||||
HeapMapper::HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, Core::Asid asid,
|
||||
Tegra::Host1x::Host1x& host1x)
|
||||
: m_vaddress{start_vaddress}, m_daddress{start_daddress}, m_size{size}, m_smmu_id{smmu_id} {
|
||||
: m_vaddress{start_vaddress}, m_daddress{start_daddress}, m_size{size}, m_asid{asid} {
|
||||
m_internal = std::make_unique<HeapMapperInternal>(host1x);
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ DAddr HeapMapper::Map(VAddr start, size_t size) {
|
||||
const size_t offset = inter_addr - m_vaddress;
|
||||
const size_t sub_size = inter_addr_end - inter_addr;
|
||||
m_internal->device_memory.Map(m_daddress + offset, m_vaddress + offset, sub_size,
|
||||
m_smmu_id);
|
||||
m_asid);
|
||||
}
|
||||
}
|
||||
m_internal->mapping_overlaps += std::make_pair(interval, 1);
|
||||
@@ -172,4 +172,4 @@ void HeapMapper::Unmap(VAddr start, size_t size) {
|
||||
m_internal->base_set.clear();
|
||||
}
|
||||
|
||||
} // namespace Service::Nvidia::NvCore
|
||||
} // namespace Service::Nvidia::NvCore
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/device_memory_manager.h"
|
||||
|
||||
namespace Tegra::Host1x {
|
||||
class Host1x;
|
||||
@@ -15,7 +16,7 @@ namespace Service::Nvidia::NvCore {
|
||||
|
||||
class HeapMapper {
|
||||
public:
|
||||
HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, size_t smmu_id,
|
||||
HeapMapper(VAddr start_vaddress, DAddr start_daddress, size_t size, Core::Asid asid,
|
||||
Tegra::Host1x::Host1x& host1x);
|
||||
~HeapMapper();
|
||||
|
||||
@@ -41,8 +42,8 @@ private:
|
||||
VAddr m_vaddress;
|
||||
DAddr m_daddress;
|
||||
size_t m_size;
|
||||
size_t m_smmu_id;
|
||||
Core::Asid m_asid;
|
||||
std::unique_ptr<HeapMapperInternal> m_internal;
|
||||
};
|
||||
|
||||
} // namespace Service::Nvidia::NvCore
|
||||
} // namespace Service::Nvidia::NvCore
|
||||
|
||||
@@ -22,7 +22,8 @@ NvMap::Handle::Handle(u64 size_, Id id_)
|
||||
flags.raw = 0;
|
||||
}
|
||||
|
||||
NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress, size_t pSessionId) {
|
||||
NvResult NvMap::Handle::Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress,
|
||||
NvCore::SessionId pSessionId) {
|
||||
std::scoped_lock lock(mutex);
|
||||
// Handles cannot be allocated twice
|
||||
if (allocated) {
|
||||
@@ -223,7 +224,7 @@ DAddr NvMap::PinHandle(NvMap::Handle::Id handle, bool low_area_pin) {
|
||||
}
|
||||
|
||||
handle_description->d_address = address;
|
||||
smmu.Map(address, vaddress, map_size, session->smmu_id, true);
|
||||
smmu.Map(address, vaddress, map_size, session->asid, true);
|
||||
handle_description->in_heap = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
|
||||
namespace Tegra {
|
||||
@@ -71,7 +72,7 @@ public:
|
||||
u8 kind{}; //!< Used for memory compression
|
||||
bool allocated{}; //!< If the handle has been allocated with `Alloc`
|
||||
bool in_heap{};
|
||||
size_t session_id{};
|
||||
NvCore::SessionId session_id{};
|
||||
|
||||
DAddr d_address{}; //!< The memory location in the device's AS that this handle corresponds
|
||||
//!< to, this can also be in the nvdrv tmem
|
||||
@@ -83,7 +84,7 @@ public:
|
||||
* if a 0 address is passed
|
||||
*/
|
||||
[[nodiscard]] NvResult Alloc(Flags pFlags, u32 pAlign, u8 pKind, u64 pAddress,
|
||||
size_t pSessionId);
|
||||
NvCore::SessionId pSessionId);
|
||||
|
||||
/**
|
||||
* @brief Increases the dupe counter of the handle for the given session
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
|
||||
namespace Core {
|
||||
@@ -62,7 +63,7 @@ public:
|
||||
* Called once a device is opened
|
||||
* @param fd The device fd
|
||||
*/
|
||||
virtual void OnOpen(size_t session_id, DeviceFD fd) = 0;
|
||||
virtual void OnOpen(NvCore::SessionId session_id, DeviceFD fd) = 0;
|
||||
|
||||
/**
|
||||
* Called once a device is closed
|
||||
|
||||
@@ -35,7 +35,7 @@ NvResult nvdisp_disp0::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvdisp_disp0::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||
void nvdisp_disp0::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
||||
void nvdisp_disp0::OnClose(DeviceFD fd) {}
|
||||
|
||||
void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, android::PixelFormat format, u32 width,
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
/// Performs a screen flip, drawing the buffer pointed to by the handle.
|
||||
|
||||
@@ -86,7 +86,7 @@ NvResult nvhost_as_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> i
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_as_gpu::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||
void nvhost_as_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
||||
void nvhost_as_gpu::OnClose(DeviceFD fd) {}
|
||||
|
||||
NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
Kernel::KEvent* QueryEvent(u32 event_id) override;
|
||||
|
||||
@@ -76,7 +76,7 @@ NvResult nvhost_ctrl::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inp
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_ctrl::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||
void nvhost_ctrl::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
||||
|
||||
void nvhost_ctrl::OnClose(DeviceFD fd) {}
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
Kernel::KEvent* QueryEvent(u32 event_id) override;
|
||||
|
||||
@@ -82,7 +82,7 @@ NvResult nvhost_ctrl_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8>
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_ctrl_gpu::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||
void nvhost_ctrl_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
||||
void nvhost_ctrl_gpu::OnClose(DeviceFD fd) {}
|
||||
|
||||
NvResult nvhost_ctrl_gpu::GetCharacteristics1(IoctlCharacteristics& params) {
|
||||
|
||||
@@ -28,7 +28,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
Kernel::KEvent* QueryEvent(u32 event_id) override;
|
||||
|
||||
@@ -120,7 +120,7 @@ NvResult nvhost_gpu::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_gpu::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||
void nvhost_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
||||
void nvhost_gpu::OnClose(DeviceFD fd) {}
|
||||
|
||||
NvResult nvhost_gpu::SetNVMAPfd(IoctlSetNvmapFD& params) {
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
Kernel::KEvent* QueryEvent(u32 event_id) override;
|
||||
|
||||
@@ -68,7 +68,7 @@ NvResult nvhost_nvdec::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_nvdec::OnOpen(size_t session_id, DeviceFD fd) {
|
||||
void nvhost_nvdec::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
|
||||
LOG_INFO(Service_NVDRV, "NVDEC video stream started");
|
||||
system.SetNVDECActive(true);
|
||||
sessions[fd] = session_id;
|
||||
|
||||
@@ -20,7 +20,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
};
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ protected:
|
||||
NvCore::NvMap& nvmap;
|
||||
NvCore::ChannelType channel_type;
|
||||
std::array<u32, MaxSyncPoints> device_syncpoints{};
|
||||
std::unordered_map<DeviceFD, size_t> sessions;
|
||||
std::unordered_map<DeviceFD, NvCore::SessionId> sessions;
|
||||
};
|
||||
}; // namespace Devices
|
||||
} // namespace Service::Nvidia
|
||||
|
||||
@@ -44,7 +44,7 @@ NvResult nvhost_nvjpg::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> in
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_nvjpg::OnOpen(size_t session_id, DeviceFD fd) {}
|
||||
void nvhost_nvjpg::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
||||
void nvhost_nvjpg::OnClose(DeviceFD fd) {}
|
||||
|
||||
NvResult nvhost_nvjpg::SetNVMAPfd(IoctlSetNvmapFD& params) {
|
||||
|
||||
@@ -22,7 +22,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -68,7 +68,7 @@ NvResult nvhost_vic::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> inpu
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvhost_vic::OnOpen(size_t session_id, DeviceFD fd) {
|
||||
void nvhost_vic::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
|
||||
sessions[fd] = session_id;
|
||||
}
|
||||
|
||||
@@ -78,10 +78,7 @@ void nvhost_vic::OnClose(DeviceFD fd) {
|
||||
if (iter != host1x_file.fd_to_id.end()) {
|
||||
system.GPU().ClearCdmaInstance(iter->second);
|
||||
}
|
||||
auto it = sessions.find(fd);
|
||||
if (it != sessions.end()) {
|
||||
sessions.erase(it);
|
||||
}
|
||||
sessions.erase(fd);
|
||||
}
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
};
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -67,7 +67,7 @@ NvResult nvmap::Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, st
|
||||
return NvResult::NotImplemented;
|
||||
}
|
||||
|
||||
void nvmap::OnOpen(size_t session_id, DeviceFD fd) {
|
||||
void nvmap::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {
|
||||
sessions[fd] = session_id;
|
||||
}
|
||||
void nvmap::OnClose(DeviceFD fd) {
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
NvResult Ioctl3(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output,
|
||||
std::span<u8> inline_output) override;
|
||||
|
||||
void OnOpen(size_t session_id, DeviceFD fd) override;
|
||||
void OnOpen(NvCore::SessionId session_id, DeviceFD fd) override;
|
||||
void OnClose(DeviceFD fd) override;
|
||||
|
||||
enum class HandleParameterType : u32_le {
|
||||
@@ -115,7 +115,7 @@ private:
|
||||
|
||||
NvCore::Container& container;
|
||||
NvCore::NvMap& file;
|
||||
std::unordered_map<DeviceFD, size_t> sessions;
|
||||
std::unordered_map<DeviceFD, NvCore::SessionId> sessions;
|
||||
};
|
||||
|
||||
} // namespace Service::Nvidia::Devices
|
||||
|
||||
@@ -52,15 +52,15 @@ void LoopProcess(Nvnflinger::Nvnflinger& nvnflinger, Core::System& system) {
|
||||
return std::make_shared<NVDRV>(system, module, "nvdrv:a");
|
||||
};
|
||||
const auto NvdrvInterfaceFactoryForSysmodules = [&, module] {
|
||||
return std::make_shared<NVDRV>(system, module, "nvdrv:a");
|
||||
return std::make_shared<NVDRV>(system, module, "nvdrv:s");
|
||||
};
|
||||
const auto NvdrvInterfaceFactory = [&, module] {
|
||||
const auto NvdrvInterfaceFactoryForTesting = [&, module] {
|
||||
return std::make_shared<NVDRV>(system, module, "nvdrv:t");
|
||||
};
|
||||
server_manager->RegisterNamedService("nvdrv", NvdrvInterfaceFactoryForApplication);
|
||||
server_manager->RegisterNamedService("nvdrv:a", NvdrvInterfaceFactoryForApplets);
|
||||
server_manager->RegisterNamedService("nvdrv:s", NvdrvInterfaceFactoryForSysmodules);
|
||||
server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactory);
|
||||
server_manager->RegisterNamedService("nvdrv:t", NvdrvInterfaceFactoryForTesting);
|
||||
server_manager->RegisterNamedService("nvmemp", std::make_shared<NVMEMP>(system));
|
||||
nvnflinger.SetNVDrvInstance(module);
|
||||
ServerManager::RunServer(std::move(server_manager));
|
||||
@@ -122,7 +122,7 @@ NvResult Module::VerifyFD(DeviceFD fd) const {
|
||||
return NvResult::Success;
|
||||
}
|
||||
|
||||
DeviceFD Module::Open(const std::string& device_name, size_t session_id) {
|
||||
DeviceFD Module::Open(const std::string& device_name, NvCore::SessionId session_id) {
|
||||
auto it = builders.find(device_name);
|
||||
if (it == builders.end()) {
|
||||
LOG_ERROR(Service_NVDRV, "Trying to open unknown device {}", device_name);
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
NvResult VerifyFD(DeviceFD fd) const;
|
||||
|
||||
/// Opens a device node and returns a file descriptor to it.
|
||||
DeviceFD Open(const std::string& device_name, size_t session_id);
|
||||
DeviceFD Open(const std::string& device_name, NvCore::SessionId session_id);
|
||||
|
||||
/// Sends an ioctl command to the specified file descriptor.
|
||||
NvResult Ioctl1(DeviceFD fd, Ioctl command, std::span<const u8> input, std::span<u8> output);
|
||||
|
||||
@@ -35,7 +35,7 @@ private:
|
||||
|
||||
u64 pid{};
|
||||
bool is_initialized{};
|
||||
size_t session_id{};
|
||||
NvCore::SessionId session_id{};
|
||||
Common::ScratchBuffer<u8> output_buffer;
|
||||
Common::ScratchBuffer<u8> inline_output_buffer;
|
||||
};
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "common/math_util.h"
|
||||
#include "core/hle/service/nvdrv/core/container.h"
|
||||
#include "core/hle/service/nvdrv/nvdata.h"
|
||||
#include "core/hle/service/nvnflinger/nvnflinger.h"
|
||||
#include "core/hle/service/nvnflinger/ui/fence.h"
|
||||
@@ -55,7 +56,7 @@ private:
|
||||
u32 m_buffer_nvmap_handle = 0;
|
||||
SharedMemoryPoolLayout m_pool_layout = {};
|
||||
Nvidia::DeviceFD m_nvmap_fd = {};
|
||||
size_t m_session_id = {};
|
||||
Nvidia::NvCore::SessionId m_session_id = {};
|
||||
std::unique_ptr<Kernel::KPageGroup> m_buffer_page_group;
|
||||
|
||||
std::mutex m_guard;
|
||||
|
||||
@@ -126,7 +126,7 @@ void Nvnflinger::ShutdownLayers() {
|
||||
|
||||
void Nvnflinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
|
||||
nvdrv = std::move(instance);
|
||||
disp_fd = nvdrv->Open("/dev/nvdisp_disp0", 0);
|
||||
disp_fd = nvdrv->Open("/dev/nvdisp_disp0", {});
|
||||
}
|
||||
|
||||
std::optional<u64> Nvnflinger::OpenDisplay(std::string_view name) {
|
||||
|
||||
@@ -19,8 +19,54 @@
|
||||
#include "core/arm/nce/patcher.h"
|
||||
#endif
|
||||
|
||||
#ifndef HAS_NCE
|
||||
namespace Core::NCE {
|
||||
class Patcher {};
|
||||
} // namespace Core::NCE
|
||||
#endif
|
||||
|
||||
namespace Loader {
|
||||
|
||||
struct PatchCollection {
|
||||
explicit PatchCollection(bool is_application_) : is_application{is_application_} {
|
||||
module_patcher_indices.fill(-1);
|
||||
patchers.emplace_back();
|
||||
}
|
||||
|
||||
std::vector<Core::NCE::Patcher>* GetPatchers() {
|
||||
if (is_application && Settings::IsNceEnabled()) {
|
||||
return &patchers;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
size_t GetTotalPatchSize() const {
|
||||
size_t total_size{};
|
||||
#ifdef HAS_NCE
|
||||
for (auto& patcher : patchers) {
|
||||
total_size += patcher.GetSectionSize();
|
||||
}
|
||||
#endif
|
||||
return total_size;
|
||||
}
|
||||
|
||||
void SaveIndex(size_t module) {
|
||||
module_patcher_indices[module] = static_cast<s32>(patchers.size() - 1);
|
||||
}
|
||||
|
||||
s32 GetIndex(size_t module) const {
|
||||
return module_patcher_indices[module];
|
||||
}
|
||||
|
||||
s32 GetLastIndex() const {
|
||||
return static_cast<s32>(patchers.size()) - 1;
|
||||
}
|
||||
|
||||
bool is_application;
|
||||
std::vector<Core::NCE::Patcher> patchers;
|
||||
std::array<s32, 13> module_patcher_indices{};
|
||||
};
|
||||
|
||||
AppLoader_DeconstructedRomDirectory::AppLoader_DeconstructedRomDirectory(FileSys::VirtualFile file_,
|
||||
bool override_update_)
|
||||
: AppLoader(std::move(file_)), override_update(override_update_), is_hbl(false) {
|
||||
@@ -142,18 +188,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
std::size_t code_size{};
|
||||
|
||||
// Define an nce patch context for each potential module.
|
||||
#ifdef HAS_NCE
|
||||
std::array<Core::NCE::Patcher, 13> module_patchers;
|
||||
#endif
|
||||
|
||||
const auto GetPatcher = [&](size_t i) -> Core::NCE::Patcher* {
|
||||
#ifdef HAS_NCE
|
||||
if (is_application && Settings::IsNceEnabled()) {
|
||||
return &module_patchers[i];
|
||||
}
|
||||
#endif
|
||||
return nullptr;
|
||||
};
|
||||
PatchCollection patch_ctx{is_application};
|
||||
|
||||
// Use the NSO module loader to figure out the code layout
|
||||
for (size_t i = 0; i < static_modules.size(); i++) {
|
||||
@@ -164,13 +199,14 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
}
|
||||
|
||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
||||
const auto tentative_next_load_addr =
|
||||
AppLoader_NSO::LoadModule(process, system, *module_file, code_size,
|
||||
should_pass_arguments, false, {}, GetPatcher(i));
|
||||
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
|
||||
process, system, *module_file, code_size, should_pass_arguments, false, {},
|
||||
patch_ctx.GetPatchers(), patch_ctx.GetLastIndex());
|
||||
if (!tentative_next_load_addr) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
}
|
||||
|
||||
patch_ctx.SaveIndex(i);
|
||||
code_size = *tentative_next_load_addr;
|
||||
}
|
||||
|
||||
@@ -184,6 +220,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
return 0;
|
||||
}();
|
||||
|
||||
// Add patch size to the total module size
|
||||
code_size += patch_ctx.GetTotalPatchSize();
|
||||
|
||||
// Setup the process code layout
|
||||
if (process.LoadFromMetadata(metadata, code_size, fastmem_base, is_hbl).IsError()) {
|
||||
return {ResultStatus::ErrorUnableToParseKernelMetadata, {}};
|
||||
@@ -204,9 +243,9 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
||||
|
||||
const VAddr load_addr{next_load_addr};
|
||||
const bool should_pass_arguments = std::strcmp(module, "rtld") == 0;
|
||||
const auto tentative_next_load_addr =
|
||||
AppLoader_NSO::LoadModule(process, system, *module_file, load_addr,
|
||||
should_pass_arguments, true, pm, GetPatcher(i));
|
||||
const auto tentative_next_load_addr = AppLoader_NSO::LoadModule(
|
||||
process, system, *module_file, load_addr, should_pass_arguments, true, pm,
|
||||
patch_ctx.GetPatchers(), patch_ctx.GetIndex(i));
|
||||
if (!tentative_next_load_addr) {
|
||||
return {ResultStatus::ErrorLoadingNSO, {}};
|
||||
}
|
||||
|
||||
@@ -77,7 +77,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||
const FileSys::VfsFile& nso_file, VAddr load_base,
|
||||
bool should_pass_arguments, bool load_into_process,
|
||||
std::optional<FileSys::PatchManager> pm,
|
||||
Core::NCE::Patcher* patch) {
|
||||
std::vector<Core::NCE::Patcher>* patches,
|
||||
s32 patch_index) {
|
||||
if (nso_file.GetSize() < sizeof(NSOHeader)) {
|
||||
return std::nullopt;
|
||||
}
|
||||
@@ -94,8 +95,11 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||
// Allocate some space at the beginning if we are patching in PreText mode.
|
||||
const size_t module_start = [&]() -> size_t {
|
||||
#ifdef HAS_NCE
|
||||
if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::PreText) {
|
||||
return patch->GetSectionSize();
|
||||
if (patches && load_into_process) {
|
||||
auto* patch = &patches->operator[](patch_index);
|
||||
if (patch->GetPatchMode() == Core::NCE::PatchMode::PreText) {
|
||||
return patch->GetSectionSize();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
@@ -160,27 +164,24 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core::
|
||||
#ifdef HAS_NCE
|
||||
// If we are computing the process code layout and using nce backend, patch.
|
||||
const auto& code = codeset.CodeSegment();
|
||||
if (patch && patch->GetPatchMode() == Core::NCE::PatchMode::None) {
|
||||
auto* patch = patches ? &patches->operator[](patch_index) : nullptr;
|
||||
if (patch && !load_into_process) {
|
||||
// Patch SVCs and MRS calls in the guest code
|
||||
patch->PatchText(program_image, code);
|
||||
|
||||
// Add patch section size to the module size.
|
||||
image_size += static_cast<u32>(patch->GetSectionSize());
|
||||
while (!patch->PatchText(program_image, code)) {
|
||||
patch = &patches->emplace_back();
|
||||
}
|
||||
} else if (patch) {
|
||||
// Relocate code patch and copy to the program_image.
|
||||
patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers());
|
||||
|
||||
// Update patch section.
|
||||
auto& patch_segment = codeset.PatchSegment();
|
||||
patch_segment.addr =
|
||||
patch->GetPatchMode() == Core::NCE::PatchMode::PreText ? 0 : image_size;
|
||||
patch_segment.size = static_cast<u32>(patch->GetSectionSize());
|
||||
|
||||
// Add patch section size to the module size. In PreText mode image_size
|
||||
// already contains the patch segment as part of module_start.
|
||||
if (patch->GetPatchMode() == Core::NCE::PatchMode::PostData) {
|
||||
image_size += patch_segment.size;
|
||||
if (patch->RelocateAndCopy(load_base, code, program_image, &process.GetPostHandlers())) {
|
||||
// Update patch section.
|
||||
auto& patch_segment = codeset.PatchSegment();
|
||||
patch_segment.addr =
|
||||
patch->GetPatchMode() == Core::NCE::PatchMode::PreText ? 0 : image_size;
|
||||
patch_segment.size = static_cast<u32>(patch->GetSectionSize());
|
||||
}
|
||||
|
||||
// Refresh image_size to take account the patch section if it was added by RelocateAndCopy
|
||||
image_size = static_cast<u32>(program_image.size());
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -93,7 +93,8 @@ public:
|
||||
const FileSys::VfsFile& nso_file, VAddr load_base,
|
||||
bool should_pass_arguments, bool load_into_process,
|
||||
std::optional<FileSys::PatchManager> pm = {},
|
||||
Core::NCE::Patcher* patch = nullptr);
|
||||
std::vector<Core::NCE::Patcher>* patches = nullptr,
|
||||
s32 patch_index = -1);
|
||||
|
||||
LoadResult Load(Kernel::KProcess& process, Core::System& system) override;
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <array>
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "common/settings.h"
|
||||
#include "common/settings_common.h"
|
||||
#include "common/settings_enums.h"
|
||||
@@ -58,6 +59,19 @@ void Config::Initialize(const std::optional<std::string> config_path) {
|
||||
}
|
||||
|
||||
void Config::WriteToIni() const {
|
||||
std::string config_type;
|
||||
switch (type) {
|
||||
case ConfigType::GlobalConfig:
|
||||
config_type = "Global";
|
||||
break;
|
||||
case ConfigType::PerGameConfig:
|
||||
config_type = "Game Specific";
|
||||
break;
|
||||
case ConfigType::InputProfile:
|
||||
config_type = "Input Profile";
|
||||
break;
|
||||
}
|
||||
LOG_INFO(Config, "Writing {} configuration to: {}", config_type, config_loc);
|
||||
FILE* fp = nullptr;
|
||||
#ifdef _WIN32
|
||||
fp = _wfopen(Common::UTF8ToUTF16W(config_loc).data(), L"wb");
|
||||
@@ -117,10 +131,10 @@ void Config::ReadPlayerValues(const std::size_t player_index) {
|
||||
player_prefix.append("player_").append(ToString(player_index)).append("_");
|
||||
}
|
||||
|
||||
const auto profile_name = ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
||||
|
||||
auto& player = Settings::values.players.GetValue()[player_index];
|
||||
if (IsCustomConfig()) {
|
||||
const auto profile_name =
|
||||
ReadStringSetting(std::string(player_prefix).append("profile_name"));
|
||||
if (profile_name.empty()) {
|
||||
// Use the global input config
|
||||
player = Settings::values.players.GetValue(true)[player_index];
|
||||
@@ -139,6 +153,10 @@ void Config::ReadPlayerValues(const std::size_t player_index) {
|
||||
player.controller_type = controller;
|
||||
}
|
||||
} else {
|
||||
if (global) {
|
||||
auto& player_global = Settings::values.players.GetValue(true)[player_index];
|
||||
player_global.profile_name = profile_name;
|
||||
}
|
||||
std::string connected_key = player_prefix;
|
||||
player.connected = ReadBooleanSetting(connected_key.append("connected"),
|
||||
std::make_optional(player_index == 0));
|
||||
@@ -412,6 +430,11 @@ void Config::SavePlayerValues(const std::size_t player_index) {
|
||||
std::make_optional(static_cast<u8>(Settings::ControllerType::ProController)));
|
||||
|
||||
if (!player_prefix.empty() || !Settings::IsConfiguringGlobal()) {
|
||||
if (global) {
|
||||
const auto& player_global = Settings::values.players.GetValue(true)[player_index];
|
||||
WriteStringSetting(std::string(player_prefix).append("profile_name"),
|
||||
player_global.profile_name, std::make_optional(std::string("")));
|
||||
}
|
||||
WriteBooleanSetting(std::string(player_prefix).append("connected"), player.connected,
|
||||
std::make_optional(player_index == 0));
|
||||
WriteIntegerSetting(std::string(player_prefix).append("vibration_enabled"),
|
||||
@@ -468,12 +491,15 @@ void Config::SaveMotionTouchValues() {
|
||||
|
||||
void Config::SaveValues() {
|
||||
if (global) {
|
||||
LOG_DEBUG(Config, "Saving global generic configuration values");
|
||||
SaveDataStorageValues();
|
||||
SaveDebuggingValues();
|
||||
SaveDisabledAddOnValues();
|
||||
SaveNetworkValues();
|
||||
SaveWebServiceValues();
|
||||
SaveMiscellaneousValues();
|
||||
} else {
|
||||
LOG_DEBUG(Config, "Saving only generic configuration values");
|
||||
}
|
||||
SaveControlValues();
|
||||
SaveCoreValues();
|
||||
@@ -814,10 +840,6 @@ void Config::Reload() {
|
||||
SaveValues();
|
||||
}
|
||||
|
||||
void Config::Save() {
|
||||
SaveValues();
|
||||
}
|
||||
|
||||
void Config::ClearControlPlayerValues() const {
|
||||
// If key is an empty string, all keys in the current group() are removed.
|
||||
const char* section = Settings::TranslateCategory(Settings::Category::Controls);
|
||||
|
||||
@@ -51,7 +51,6 @@ protected:
|
||||
[[nodiscard]] bool IsCustomConfig() const;
|
||||
|
||||
void Reload();
|
||||
void Save();
|
||||
|
||||
/**
|
||||
* Derived config classes must implement this so they can reload all platform-specific
|
||||
|
||||
@@ -509,11 +509,11 @@ void EmulatedController::ReloadInput() {
|
||||
});
|
||||
}
|
||||
turbo_button_state = 0;
|
||||
is_initalized = true;
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
void EmulatedController::UnloadInput() {
|
||||
is_initalized = false;
|
||||
is_initialized = false;
|
||||
for (auto& button : button_devices) {
|
||||
button.reset();
|
||||
}
|
||||
@@ -1209,7 +1209,7 @@ void EmulatedController::SetNfc(const Common::Input::CallbackStatus& callback) {
|
||||
}
|
||||
|
||||
bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue vibration) {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
if (device_index >= output_devices.size()) {
|
||||
@@ -1247,7 +1247,7 @@ bool EmulatedController::IsVibrationEnabled(std::size_t device_index) {
|
||||
const auto player_index = Service::HID::NpadIdTypeToIndex(npad_id_type);
|
||||
const auto& player = Settings::values.players.GetValue()[player_index];
|
||||
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1270,7 +1270,7 @@ Common::Input::DriverResult EmulatedController::SetPollingMode(
|
||||
EmulatedDeviceIndex device_index, Common::Input::PollingMode polling_mode) {
|
||||
LOG_INFO(Service_HID, "Set polling mode {}, device_index={}", polling_mode, device_index);
|
||||
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return Common::Input::DriverResult::InvalidHandle;
|
||||
}
|
||||
|
||||
@@ -1319,7 +1319,7 @@ bool EmulatedController::SetCameraFormat(
|
||||
Core::IrSensor::ImageTransferProcessorFormat camera_format) {
|
||||
LOG_INFO(Service_HID, "Set camera format {}", camera_format);
|
||||
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1347,7 +1347,7 @@ void EmulatedController::SetRingParam(Common::ParamPackage param) {
|
||||
|
||||
bool EmulatedController::HasNfc() const {
|
||||
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1388,7 +1388,7 @@ bool EmulatedController::RemoveNfcHandle() {
|
||||
}
|
||||
|
||||
bool EmulatedController::StartNfcPolling() {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1403,7 +1403,7 @@ bool EmulatedController::StartNfcPolling() {
|
||||
}
|
||||
|
||||
bool EmulatedController::StopNfcPolling() {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1418,7 +1418,7 @@ bool EmulatedController::StopNfcPolling() {
|
||||
}
|
||||
|
||||
bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1434,7 +1434,7 @@ bool EmulatedController::ReadAmiiboData(std::vector<u8>& data) {
|
||||
|
||||
bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& request,
|
||||
Common::Input::MifareRequest& out_data) {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1450,7 +1450,7 @@ bool EmulatedController::ReadMifareData(const Common::Input::MifareRequest& requ
|
||||
}
|
||||
|
||||
bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& request) {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1465,7 +1465,7 @@ bool EmulatedController::WriteMifareData(const Common::Input::MifareRequest& req
|
||||
}
|
||||
|
||||
bool EmulatedController::WriteNfc(const std::vector<u8>& data) {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1480,7 +1480,7 @@ bool EmulatedController::WriteNfc(const std::vector<u8>& data) {
|
||||
}
|
||||
|
||||
void EmulatedController::SetLedPattern() {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1508,8 +1508,8 @@ void EmulatedController::SetGyroscopeZeroDriftMode(GyroscopeZeroDriftMode mode)
|
||||
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdLoose);
|
||||
break;
|
||||
case GyroscopeZeroDriftMode::Tight:
|
||||
motion_sensitivity = motion.emulated.IsAtRestThight;
|
||||
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdThight);
|
||||
motion_sensitivity = motion.emulated.IsAtRestTight;
|
||||
motion.emulated.SetGyroThreshold(motion.emulated.ThresholdTight);
|
||||
break;
|
||||
case GyroscopeZeroDriftMode::Standard:
|
||||
default:
|
||||
|
||||
@@ -559,7 +559,7 @@ private:
|
||||
NpadStyleTag supported_style_tag{NpadStyleSet::All};
|
||||
bool is_connected{false};
|
||||
bool is_configuring{false};
|
||||
bool is_initalized{false};
|
||||
bool is_initialized{false};
|
||||
bool system_buttons_enabled{true};
|
||||
f32 motion_sensitivity{Core::HID::MotionInput::IsAtRestStandard};
|
||||
u32 turbo_button_state{0};
|
||||
|
||||
@@ -13,12 +13,12 @@ class MotionInput {
|
||||
public:
|
||||
static constexpr float ThresholdLoose = 0.01f;
|
||||
static constexpr float ThresholdStandard = 0.007f;
|
||||
static constexpr float ThresholdThight = 0.002f;
|
||||
static constexpr float ThresholdTight = 0.002f;
|
||||
|
||||
static constexpr float IsAtRestRelaxed = 0.05f;
|
||||
static constexpr float IsAtRestLoose = 0.02f;
|
||||
static constexpr float IsAtRestStandard = 0.01f;
|
||||
static constexpr float IsAtRestThight = 0.005f;
|
||||
static constexpr float IsAtRestTight = 0.005f;
|
||||
|
||||
static constexpr float GyroMaxValue = 5.0f;
|
||||
static constexpr float AccelMaxValue = 7.0f;
|
||||
|
||||
@@ -15,7 +15,7 @@ constexpr Result ResultVibrationNotInitialized{ErrorModule::HID, 121};
|
||||
constexpr Result ResultVibrationInvalidStyleIndex{ErrorModule::HID, 122};
|
||||
constexpr Result ResultVibrationInvalidNpadId{ErrorModule::HID, 123};
|
||||
constexpr Result ResultVibrationDeviceIndexOutOfRange{ErrorModule::HID, 124};
|
||||
constexpr Result ResultVibrationStrenghtOutOfRange{ErrorModule::HID, 126};
|
||||
constexpr Result ResultVibrationStrengthOutOfRange{ErrorModule::HID, 126};
|
||||
constexpr Result ResultVibrationArraySizeMismatch{ErrorModule::HID, 131};
|
||||
|
||||
constexpr Result InvalidSixAxisFusionRange{ErrorModule::HID, 423};
|
||||
|
||||
@@ -106,8 +106,8 @@ enum class HandAnalysisMode : u32 {
|
||||
None,
|
||||
Silhouette,
|
||||
Image,
|
||||
SilhoueteAndImage,
|
||||
SilhuetteOnly,
|
||||
SilhouetteAndImage,
|
||||
SilhouetteOnly,
|
||||
};
|
||||
|
||||
// This is nn::irsensor::IrSensorFunctionLevel
|
||||
|
||||
@@ -14,7 +14,7 @@ void HidFirmwareSettings::Reload() {
|
||||
}
|
||||
|
||||
void HidFirmwareSettings::LoadSettings(bool reload_config) {
|
||||
if (is_initalized && !reload_config) {
|
||||
if (is_initialized && !reload_config) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ void HidFirmwareSettings::LoadSettings(bool reload_config) {
|
||||
is_handheld_forced = true;
|
||||
features_per_id_disabled = {};
|
||||
is_touch_firmware_auto_update_disabled = false;
|
||||
is_initalized = true;
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
bool HidFirmwareSettings::IsDebugPadEnabled() {
|
||||
|
||||
@@ -33,7 +33,7 @@ public:
|
||||
FeaturesPerId FeaturesDisabledPerId();
|
||||
|
||||
private:
|
||||
bool is_initalized{};
|
||||
bool is_initialized{};
|
||||
|
||||
// Debug settings
|
||||
bool is_debug_pad_enabled{};
|
||||
|
||||
@@ -318,7 +318,7 @@ struct InternalFlags {
|
||||
BitField<1, 1, u32> is_connected;
|
||||
BitField<2, 1, u32> is_battery_low_ovln_required;
|
||||
BitField<3, 1, u32> is_battery_low_ovln_delay_required;
|
||||
BitField<4, 1, u32> is_sample_recieved;
|
||||
BitField<4, 1, u32> is_sample_received;
|
||||
BitField<5, 1, u32> is_virtual_input;
|
||||
BitField<6, 1, u32> is_wired;
|
||||
BitField<8, 1, u32> use_center_clamp;
|
||||
|
||||
@@ -15,7 +15,7 @@ Result NpadVibration::Activate() {
|
||||
|
||||
const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
|
||||
// if (master_volume < 0.0f || master_volume > 1.0f) {
|
||||
// return ResultVibrationStrenghtOutOfRange;
|
||||
// return ResultVibrationStrengthOutOfRange;
|
||||
// }
|
||||
|
||||
volume = master_volume;
|
||||
@@ -30,7 +30,7 @@ Result NpadVibration::SetVibrationMasterVolume(f32 master_volume) {
|
||||
std::scoped_lock lock{mutex};
|
||||
|
||||
if (master_volume < 0.0f && master_volume > 1.0f) {
|
||||
return ResultVibrationStrenghtOutOfRange;
|
||||
return ResultVibrationStrengthOutOfRange;
|
||||
}
|
||||
|
||||
volume = master_volume;
|
||||
@@ -50,7 +50,7 @@ Result NpadVibration::GetVibrationMasterVolume(f32& out_volume) const {
|
||||
|
||||
const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
|
||||
// if (master_volume < 0.0f || master_volume > 1.0f) {
|
||||
// return ResultVibrationStrenghtOutOfRange;
|
||||
// return ResultVibrationStrengthOutOfRange;
|
||||
// }
|
||||
|
||||
out_volume = master_volume;
|
||||
@@ -69,7 +69,7 @@ Result NpadVibration::EndPermitVibrationSession() {
|
||||
|
||||
const f32 master_volume = 1.0f; // nn::settings::system::GetVibrationMasterVolume();
|
||||
// if (master_volume < 0.0f || master_volume > 1.0f) {
|
||||
// return ResultVibrationStrenghtOutOfRange;
|
||||
// return ResultVibrationStrengthOutOfRange;
|
||||
// }
|
||||
|
||||
volume = master_volume;
|
||||
|
||||
@@ -249,7 +249,7 @@ Result SixAxis::EnableSixAxisSensorUnalteredPassthrough(
|
||||
}
|
||||
|
||||
auto& sixaxis = GetSixaxisState(sixaxis_handle);
|
||||
sixaxis.unaltered_passtrough = is_enabled;
|
||||
sixaxis.unaltered_passthrough = is_enabled;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ Result SixAxis::IsSixAxisSensorUnalteredPassthroughEnabled(
|
||||
}
|
||||
|
||||
const auto& sixaxis = GetSixaxisState(sixaxis_handle);
|
||||
is_enabled = sixaxis.unaltered_passtrough;
|
||||
is_enabled = sixaxis.unaltered_passthrough;
|
||||
return ResultSuccess;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ private:
|
||||
|
||||
struct SixaxisParameters {
|
||||
bool is_fusion_enabled{true};
|
||||
bool unaltered_passtrough{false};
|
||||
bool unaltered_passthrough{false};
|
||||
Core::HID::SixAxisSensorFusionParameters fusion{};
|
||||
Core::HID::SixAxisSensorCalibrationParameter calibration{};
|
||||
Core::HID::SixAxisSensorIcInformation ic_information{};
|
||||
|
||||
@@ -451,11 +451,11 @@ ButtonMapping GCAdapter::GetButtonMappingForDevice(const Common::ParamPackage& p
|
||||
std::tuple{Settings::NativeButton::ZL, PadButton::TriggerL, PadAxes::TriggerLeft},
|
||||
{Settings::NativeButton::ZR, PadButton::TriggerR, PadAxes::TriggerRight},
|
||||
};
|
||||
for (const auto& [switch_button, gcadapter_buton, gcadapter_axis] : switch_to_gcadapter_axis) {
|
||||
for (const auto& [switch_button, gcadapter_button, gcadapter_axis] : switch_to_gcadapter_axis) {
|
||||
Common::ParamPackage button_params{};
|
||||
button_params.Set("engine", GetEngineName());
|
||||
button_params.Set("port", params.Get("port", 0));
|
||||
button_params.Set("button", static_cast<s32>(gcadapter_buton));
|
||||
button_params.Set("button", static_cast<s32>(gcadapter_button));
|
||||
button_params.Set("axis", static_cast<s32>(gcadapter_axis));
|
||||
button_params.Set("threshold", 0.5f);
|
||||
button_params.Set("range", 1.9f);
|
||||
|
||||
@@ -236,9 +236,9 @@ Common::Input::DriverResult IrsProtocol::WriteRegistersStep2() {
|
||||
.number_of_registers = 0x8,
|
||||
.registers =
|
||||
{
|
||||
IrsRegister{IrRegistersAddress::LedIntensitiyMSB,
|
||||
IrsRegister{IrRegistersAddress::LedIntensityMSB,
|
||||
static_cast<u8>(led_intensity >> 8)},
|
||||
{IrRegistersAddress::LedIntensitiyLSB, static_cast<u8>(led_intensity & 0xff)},
|
||||
{IrRegistersAddress::LedIntensityLSB, static_cast<u8>(led_intensity & 0xff)},
|
||||
{IrRegistersAddress::ImageFlip, static_cast<u8>(image_flip)},
|
||||
{IrRegistersAddress::DenoiseSmoothing, static_cast<u8>((denoise >> 16) & 0xff)},
|
||||
{IrRegistersAddress::DenoiseEdge, static_cast<u8>((denoise >> 8) & 0xff)},
|
||||
|
||||
@@ -282,7 +282,7 @@ enum class NFCCommand : u8 {
|
||||
CancelAll = 0x00,
|
||||
StartPolling = 0x01,
|
||||
StopPolling = 0x02,
|
||||
StartWaitingRecieve = 0x04,
|
||||
StartWaitingReceive = 0x04,
|
||||
ReadNtag = 0x06,
|
||||
WriteNtag = 0x08,
|
||||
Mifare = 0x0F,
|
||||
@@ -382,8 +382,8 @@ enum class IrRegistersAddress : u16 {
|
||||
FinalizeConfig = 0x0700,
|
||||
LedFilter = 0x0e00,
|
||||
Leds = 0x1000,
|
||||
LedIntensitiyMSB = 0x1100,
|
||||
LedIntensitiyLSB = 0x1200,
|
||||
LedIntensityMSB = 0x1100,
|
||||
LedIntensityLSB = 0x1200,
|
||||
ImageFlip = 0x2d00,
|
||||
Resolution = 0x2e00,
|
||||
DigitalGainLSB = 0x2e01,
|
||||
|
||||
@@ -519,13 +519,13 @@ Common::Input::DriverResult NfcProtocol::GetMifareData(
|
||||
}
|
||||
|
||||
if (output.mcu_report == MCUReport::NFCState && output.mcu_data[1] == 0x10) {
|
||||
constexpr std::size_t DATA_LENGHT = 0x10 + 1;
|
||||
constexpr std::size_t DATA_LENGTH = 0x10 + 1;
|
||||
constexpr std::size_t DATA_START = 11;
|
||||
const u8 number_of_elements = output.mcu_data[10];
|
||||
for (std::size_t i = 0; i < number_of_elements; i++) {
|
||||
out_data[i].sector = output.mcu_data[DATA_START + (i * DATA_LENGHT)];
|
||||
out_data[i].sector = output.mcu_data[DATA_START + (i * DATA_LENGTH)];
|
||||
memcpy(out_data[i].data.data(),
|
||||
output.mcu_data.data() + DATA_START + 1 + (i * DATA_LENGHT),
|
||||
output.mcu_data.data() + DATA_START + 1 + (i * DATA_LENGTH),
|
||||
sizeof(MifareReadData::data));
|
||||
}
|
||||
package_index++;
|
||||
@@ -659,7 +659,7 @@ Common::Input::DriverResult NfcProtocol::SendStopPollingRequest(MCUCommandRespon
|
||||
Common::Input::DriverResult NfcProtocol::SendNextPackageRequest(MCUCommandResponse& output,
|
||||
u8 packet_id) {
|
||||
NFCRequestState request{
|
||||
.command_argument = NFCCommand::StartWaitingRecieve,
|
||||
.command_argument = NFCCommand::StartWaitingReceive,
|
||||
.block_id = {},
|
||||
.packet_id = packet_id,
|
||||
.packet_flag = MCUPacketFlag::LastCommandPacket,
|
||||
|
||||
@@ -67,7 +67,7 @@ u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
|
||||
// More information about these values can be found here:
|
||||
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
|
||||
|
||||
static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
|
||||
static constexpr std::array<std::pair<f32, int>, 101> high_frequency_amplitude{
|
||||
std::pair<f32, int>{0.0f, 0x0},
|
||||
{0.01f, 0x2},
|
||||
{0.012f, 0x4},
|
||||
@@ -171,20 +171,20 @@ u8 RumbleProtocol::EncodeHighAmplitude(f32 amplitude) const {
|
||||
{1.003f, 0xc8},
|
||||
};
|
||||
|
||||
for (const auto& [amplitude_value, code] : high_fequency_amplitude) {
|
||||
for (const auto& [amplitude_value, code] : high_frequency_amplitude) {
|
||||
if (amplitude <= amplitude_value) {
|
||||
return static_cast<u8>(code);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<u8>(high_fequency_amplitude[high_fequency_amplitude.size() - 1].second);
|
||||
return static_cast<u8>(high_frequency_amplitude[high_frequency_amplitude.size() - 1].second);
|
||||
}
|
||||
|
||||
u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const {
|
||||
// More information about these values can be found here:
|
||||
// https://github.com/dekuNukem/Nintendo_Switch_Reverse_Engineering/blob/master/rumble_data_table.md
|
||||
|
||||
static constexpr std::array<std::pair<f32, int>, 101> high_fequency_amplitude{
|
||||
static constexpr std::array<std::pair<f32, int>, 101> high_frequency_amplitude{
|
||||
std::pair<f32, int>{0.0f, 0x0040},
|
||||
{0.01f, 0x8040},
|
||||
{0.012f, 0x0041},
|
||||
@@ -288,13 +288,13 @@ u16 RumbleProtocol::EncodeLowAmplitude(f32 amplitude) const {
|
||||
{1.003f, 0x0072},
|
||||
};
|
||||
|
||||
for (const auto& [amplitude_value, code] : high_fequency_amplitude) {
|
||||
for (const auto& [amplitude_value, code] : high_frequency_amplitude) {
|
||||
if (amplitude <= amplitude_value) {
|
||||
return static_cast<u16>(code);
|
||||
}
|
||||
}
|
||||
|
||||
return static_cast<u16>(high_fequency_amplitude[high_fequency_amplitude.size() - 1].second);
|
||||
return static_cast<u16>(high_frequency_amplitude[high_frequency_amplitude.size() - 1].second);
|
||||
}
|
||||
|
||||
} // namespace InputCommon::Joycon
|
||||
|
||||
@@ -78,7 +78,7 @@ namespace Request {
|
||||
enum RegisterFlags : u8 {
|
||||
AllPads,
|
||||
PadID,
|
||||
PadMACAdddress,
|
||||
PadMACAddress,
|
||||
};
|
||||
|
||||
struct Version {};
|
||||
|
||||
@@ -724,7 +724,7 @@ RoomMember::CallbackHandle<RoomInformation> RoomMember::BindOnRoomInformationCha
|
||||
return room_member_impl->Bind(callback);
|
||||
}
|
||||
|
||||
RoomMember::CallbackHandle<ChatEntry> RoomMember::BindOnChatMessageRecieved(
|
||||
RoomMember::CallbackHandle<ChatEntry> RoomMember::BindOnChatMessageReceived(
|
||||
std::function<void(const ChatEntry&)> callback) {
|
||||
return room_member_impl->Bind(callback);
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ public:
|
||||
* @param callback The function to call
|
||||
* @return A handle used for removing the function from the registered list
|
||||
*/
|
||||
CallbackHandle<ChatEntry> BindOnChatMessageRecieved(
|
||||
CallbackHandle<ChatEntry> BindOnChatMessageReceived(
|
||||
std::function<void(const ChatEntry&)> callback);
|
||||
|
||||
/**
|
||||
|
||||
@@ -608,8 +608,8 @@ std::string EmitContext::DefineGlobalMemoryFunctions() {
|
||||
const auto aligned_low_addr{fmt::format("{}&{}", addr_xy[0], ssbo_align_mask)};
|
||||
const auto aligned_addr{fmt::format("uvec2({},{})", aligned_low_addr, addr_xy[1])};
|
||||
const auto addr_pack{fmt::format("packUint2x32({})", aligned_addr)};
|
||||
const auto addr_statment{fmt::format("uint64_t {}={};", ssbo_addr, addr_pack)};
|
||||
func += addr_statment;
|
||||
const auto addr_statement{fmt::format("uint64_t {}={};", ssbo_addr, addr_pack)};
|
||||
func += addr_statement;
|
||||
|
||||
const auto size_vec{fmt::format("uvec2({},{})", size_xy[0], size_xy[1])};
|
||||
const auto comp_lhs{fmt::format("(addr>={})", ssbo_addr)};
|
||||
|
||||
@@ -12,6 +12,11 @@ namespace Shader::Backend::SPIRV {
|
||||
namespace {
|
||||
class ImageOperands {
|
||||
public:
|
||||
[[maybe_unused]] static constexpr bool ImageSampleOffsetAllowed = false;
|
||||
[[maybe_unused]] static constexpr bool ImageGatherOffsetAllowed = true;
|
||||
[[maybe_unused]] static constexpr bool ImageFetchOffsetAllowed = false;
|
||||
[[maybe_unused]] static constexpr bool ImageGradientOffsetAllowed = false;
|
||||
|
||||
explicit ImageOperands(EmitContext& ctx, bool has_bias, bool has_lod, bool has_lod_clamp,
|
||||
Id lod, const IR::Value& offset) {
|
||||
if (has_bias) {
|
||||
@@ -22,7 +27,7 @@ public:
|
||||
const Id lod_value{has_lod_clamp ? ctx.OpCompositeExtract(ctx.F32[1], lod, 0) : lod};
|
||||
Add(spv::ImageOperandsMask::Lod, lod_value);
|
||||
}
|
||||
AddOffset(ctx, offset);
|
||||
AddOffset(ctx, offset, ImageSampleOffsetAllowed);
|
||||
if (has_lod_clamp) {
|
||||
const Id lod_clamp{has_bias ? ctx.OpCompositeExtract(ctx.F32[1], lod, 1) : lod};
|
||||
Add(spv::ImageOperandsMask::MinLod, lod_clamp);
|
||||
@@ -55,20 +60,17 @@ public:
|
||||
Add(spv::ImageOperandsMask::ConstOffsets, offsets);
|
||||
}
|
||||
|
||||
explicit ImageOperands(Id offset, Id lod, Id ms) {
|
||||
explicit ImageOperands(Id lod, Id ms) {
|
||||
if (Sirit::ValidId(lod)) {
|
||||
Add(spv::ImageOperandsMask::Lod, lod);
|
||||
}
|
||||
if (Sirit::ValidId(offset)) {
|
||||
Add(spv::ImageOperandsMask::Offset, offset);
|
||||
}
|
||||
if (Sirit::ValidId(ms)) {
|
||||
Add(spv::ImageOperandsMask::Sample, ms);
|
||||
}
|
||||
}
|
||||
|
||||
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives,
|
||||
u32 num_derivatives, Id offset, Id lod_clamp) {
|
||||
u32 num_derivatives, const IR::Value& offset, Id lod_clamp) {
|
||||
if (!Sirit::ValidId(derivatives)) {
|
||||
throw LogicError("Derivatives must be present");
|
||||
}
|
||||
@@ -83,16 +85,14 @@ public:
|
||||
const Id derivatives_Y{ctx.OpCompositeConstruct(
|
||||
ctx.F32[num_derivatives], std::span{deriv_y_accum.data(), deriv_y_accum.size()})};
|
||||
Add(spv::ImageOperandsMask::Grad, derivatives_X, derivatives_Y);
|
||||
if (Sirit::ValidId(offset)) {
|
||||
Add(spv::ImageOperandsMask::Offset, offset);
|
||||
}
|
||||
AddOffset(ctx, offset, ImageGradientOffsetAllowed);
|
||||
if (has_lod_clamp) {
|
||||
Add(spv::ImageOperandsMask::MinLod, lod_clamp);
|
||||
}
|
||||
}
|
||||
|
||||
explicit ImageOperands(EmitContext& ctx, bool has_lod_clamp, Id derivatives_1, Id derivatives_2,
|
||||
Id offset, Id lod_clamp) {
|
||||
const IR::Value& offset, Id lod_clamp) {
|
||||
if (!Sirit::ValidId(derivatives_1) || !Sirit::ValidId(derivatives_2)) {
|
||||
throw LogicError("Derivatives must be present");
|
||||
}
|
||||
@@ -111,9 +111,7 @@ public:
|
||||
const Id derivatives_id2{ctx.OpCompositeConstruct(
|
||||
ctx.F32[3], std::span{deriv_2_accum.data(), deriv_2_accum.size()})};
|
||||
Add(spv::ImageOperandsMask::Grad, derivatives_id1, derivatives_id2);
|
||||
if (Sirit::ValidId(offset)) {
|
||||
Add(spv::ImageOperandsMask::Offset, offset);
|
||||
}
|
||||
AddOffset(ctx, offset, ImageGradientOffsetAllowed);
|
||||
if (has_lod_clamp) {
|
||||
Add(spv::ImageOperandsMask::MinLod, lod_clamp);
|
||||
}
|
||||
@@ -132,7 +130,7 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
void AddOffset(EmitContext& ctx, const IR::Value& offset) {
|
||||
void AddOffset(EmitContext& ctx, const IR::Value& offset, bool runtime_offset_allowed) {
|
||||
if (offset.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
@@ -165,7 +163,9 @@ private:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Add(spv::ImageOperandsMask::Offset, ctx.Def(offset));
|
||||
if (runtime_offset_allowed) {
|
||||
Add(spv::ImageOperandsMask::Offset, ctx.Def(offset));
|
||||
}
|
||||
}
|
||||
|
||||
void Add(spv::ImageOperandsMask new_mask, Id value) {
|
||||
@@ -311,6 +311,37 @@ Id ImageGatherSubpixelOffset(EmitContext& ctx, const IR::TextureInstInfo& info,
|
||||
return coords;
|
||||
}
|
||||
}
|
||||
|
||||
void AddOffsetToCoordinates(EmitContext& ctx, const IR::TextureInstInfo& info, Id& coords,
|
||||
Id offset) {
|
||||
if (!Sirit::ValidId(offset)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Id result_type{};
|
||||
switch (info.type) {
|
||||
case TextureType::Buffer:
|
||||
case TextureType::Color1D:
|
||||
case TextureType::ColorArray1D: {
|
||||
result_type = ctx.U32[1];
|
||||
break;
|
||||
}
|
||||
case TextureType::Color2D:
|
||||
case TextureType::Color2DRect:
|
||||
case TextureType::ColorArray2D: {
|
||||
result_type = ctx.U32[2];
|
||||
break;
|
||||
}
|
||||
case TextureType::Color3D: {
|
||||
result_type = ctx.U32[3];
|
||||
break;
|
||||
}
|
||||
case TextureType::ColorCube:
|
||||
case TextureType::ColorArrayCube:
|
||||
return;
|
||||
}
|
||||
coords = ctx.OpIAdd(result_type, coords, offset);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
Id EmitBindlessImageSampleImplicitLod(EmitContext&) {
|
||||
@@ -496,6 +527,7 @@ Id EmitImageGatherDref(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
|
||||
Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id offset,
|
||||
Id lod, Id ms) {
|
||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||
AddOffsetToCoordinates(ctx, info, coords, offset);
|
||||
if (info.type == TextureType::Buffer) {
|
||||
lod = Id{};
|
||||
}
|
||||
@@ -503,7 +535,7 @@ Id EmitImageFetch(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id c
|
||||
// This image is multisampled, lod must be implicit
|
||||
lod = Id{};
|
||||
}
|
||||
const ImageOperands operands(offset, lod, ms);
|
||||
const ImageOperands operands(lod, ms);
|
||||
return Emit(&EmitContext::OpImageSparseFetch, &EmitContext::OpImageFetch, ctx, inst, ctx.F32[4],
|
||||
TextureImage(ctx, info, index), coords, operands.MaskOptional(), operands.Span());
|
||||
}
|
||||
@@ -548,13 +580,13 @@ Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, I
|
||||
}
|
||||
|
||||
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||
Id derivatives, Id offset, Id lod_clamp) {
|
||||
Id derivatives, const IR::Value& offset, Id lod_clamp) {
|
||||
const auto info{inst->Flags<IR::TextureInstInfo>()};
|
||||
const auto operands =
|
||||
info.num_derivatives == 3
|
||||
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, offset, {}, lod_clamp)
|
||||
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives, info.num_derivatives, offset,
|
||||
lod_clamp);
|
||||
const auto operands = info.num_derivatives == 3
|
||||
? ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
|
||||
ctx.Def(offset), {}, lod_clamp)
|
||||
: ImageOperands(ctx, info.has_lod_clamp != 0, derivatives,
|
||||
info.num_derivatives, offset, lod_clamp);
|
||||
return Emit(&EmitContext::OpImageSparseSampleExplicitLod,
|
||||
&EmitContext::OpImageSampleExplicitLod, ctx, inst, ctx.F32[4],
|
||||
Texture(ctx, info, index), coords, operands.Mask(), operands.Span());
|
||||
|
||||
@@ -543,7 +543,7 @@ Id EmitImageQueryDimensions(EmitContext& ctx, IR::Inst* inst, const IR::Value& i
|
||||
const IR::Value& skip_mips);
|
||||
Id EmitImageQueryLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
|
||||
Id EmitImageGradient(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords,
|
||||
Id derivatives, Id offset, Id lod_clamp);
|
||||
Id derivatives, const IR::Value& offset, Id lod_clamp);
|
||||
Id EmitImageRead(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords);
|
||||
void EmitImageWrite(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, Id coords, Id color);
|
||||
Id EmitIsTextureScaled(EmitContext& ctx, const IR::Value& index);
|
||||
|
||||
@@ -329,7 +329,7 @@ void PresentManager::CopyToSwapchainImpl(Frame* frame) {
|
||||
// to account for that.
|
||||
const bool is_suboptimal = swapchain.NeedsRecreation();
|
||||
const bool size_changed =
|
||||
swapchain.GetWidth() < frame->width || swapchain.GetHeight() < frame->height;
|
||||
swapchain.GetWidth() != frame->width || swapchain.GetHeight() != frame->height;
|
||||
if (is_suboptimal || size_changed) {
|
||||
RecreateSwapchain(frame);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
/// Requests to begin a renderpass.
|
||||
void RequestRenderpass(const Framebuffer* framebuffer);
|
||||
|
||||
/// Requests the current executino context to be able to execute operations only allowed outside
|
||||
/// Requests the current execution context to be able to execute operations only allowed outside
|
||||
/// of a renderpass.
|
||||
void RequestOutsideRenderPassOperationContext();
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent,
|
||||
QtAmiiboSettingsDialog::~QtAmiiboSettingsDialog() = default;
|
||||
|
||||
int QtAmiiboSettingsDialog::exec() {
|
||||
if (!is_initalized) {
|
||||
if (!is_initialized) {
|
||||
return QDialog::Rejected;
|
||||
}
|
||||
return QDialog::exec();
|
||||
@@ -66,7 +66,7 @@ void QtAmiiboSettingsDialog::LoadInfo() {
|
||||
QString::fromStdString(input_subsystem->GetVirtualAmiibo()->GetLastFilePath()));
|
||||
|
||||
SetSettingsDescription();
|
||||
is_initalized = true;
|
||||
is_initialized = true;
|
||||
}
|
||||
|
||||
void QtAmiiboSettingsDialog::LoadAmiiboInfo() {
|
||||
|
||||
@@ -58,7 +58,7 @@ private:
|
||||
Core::Frontend::CabinetParameters parameters;
|
||||
|
||||
// If false amiibo settings failed to load
|
||||
bool is_initalized{};
|
||||
bool is_initialized{};
|
||||
};
|
||||
|
||||
class QtAmiiboSettings final : public QObject, public Core::Frontend::CabinetApplet {
|
||||
|
||||
@@ -170,7 +170,7 @@ public:
|
||||
|
||||
void resizeEvent(QResizeEvent* event) override;
|
||||
|
||||
/// Converts a Qt keybard key into NativeKeyboard key
|
||||
/// Converts a Qt keyboard key into NativeKeyboard key
|
||||
static int QtKeyToSwitchKey(Qt::Key qt_keys);
|
||||
|
||||
/// Converts a Qt modifier keys into NativeKeyboard modifier keys
|
||||
|
||||
@@ -1650,9 +1650,21 @@ void ConfigureInputPlayer::SaveProfile() {
|
||||
void ConfigureInputPlayer::UpdateInputProfiles() {
|
||||
ui->comboProfiles->clear();
|
||||
|
||||
for (const auto& profile_name : profiles->GetInputProfileNames()) {
|
||||
// Set current profile as empty by default
|
||||
int profile_index = -1;
|
||||
|
||||
// Add every available profile and search the player profile to set it as current one
|
||||
auto& current_profile = Settings::values.players.GetValue()[player_index].profile_name;
|
||||
std::vector<std::string> profile_names = profiles->GetInputProfileNames();
|
||||
std::string profile_name;
|
||||
for (size_t i = 0; i < profile_names.size(); i++) {
|
||||
profile_name = profile_names[i];
|
||||
ui->comboProfiles->addItem(QString::fromStdString(profile_name));
|
||||
if (current_profile == profile_name) {
|
||||
profile_index = (int)i;
|
||||
}
|
||||
}
|
||||
|
||||
ui->comboProfiles->setCurrentIndex(-1);
|
||||
LOG_DEBUG(Frontend, "Setting the current input profile to index {}", profile_index);
|
||||
ui->comboProfiles->setCurrentIndex(profile_index);
|
||||
}
|
||||
|
||||
@@ -845,12 +845,12 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)
|
||||
DrawSymbol(p, face_center + QPoint(-face_distance, 1), Symbol::Y, text_size);
|
||||
|
||||
// D-pad buttons
|
||||
const QPointF dpad_postion = center + QPoint(-61, 0);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Up, button_values[DUp]);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft]);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight]);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown]);
|
||||
DrawArrowButtonOutline(p, dpad_postion);
|
||||
const QPointF dpad_position = center + QPoint(-61, 0);
|
||||
DrawArrowButton(p, dpad_position, Direction::Up, button_values[DUp]);
|
||||
DrawArrowButton(p, dpad_position, Direction::Left, button_values[DLeft]);
|
||||
DrawArrowButton(p, dpad_position, Direction::Right, button_values[DRight]);
|
||||
DrawArrowButton(p, dpad_position, Direction::Down, button_values[DDown]);
|
||||
DrawArrowButtonOutline(p, dpad_position);
|
||||
|
||||
// ZL and ZR buttons
|
||||
p.setPen(colors.outline);
|
||||
@@ -935,13 +935,13 @@ void PlayerControlPreview::DrawGCController(QPainter& p, const QPointF center) {
|
||||
DrawSymbol(p, center + QPoint(100, -83), Symbol::Y, text_size);
|
||||
|
||||
// D-pad buttons
|
||||
const QPointF dpad_postion = center + QPoint(-61, 37);
|
||||
const QPointF dpad_position = center + QPoint(-61, 37);
|
||||
const float dpad_size = 0.8f;
|
||||
DrawArrowButton(p, dpad_postion, Direction::Up, button_values[DUp], dpad_size);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Left, button_values[DLeft], dpad_size);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Right, button_values[DRight], dpad_size);
|
||||
DrawArrowButton(p, dpad_postion, Direction::Down, button_values[DDown], dpad_size);
|
||||
DrawArrowButtonOutline(p, dpad_postion, dpad_size);
|
||||
DrawArrowButton(p, dpad_position, Direction::Up, button_values[DUp], dpad_size);
|
||||
DrawArrowButton(p, dpad_position, Direction::Left, button_values[DLeft], dpad_size);
|
||||
DrawArrowButton(p, dpad_position, Direction::Right, button_values[DRight], dpad_size);
|
||||
DrawArrowButton(p, dpad_position, Direction::Down, button_values[DDown], dpad_size);
|
||||
DrawArrowButtonOutline(p, dpad_position, dpad_size);
|
||||
|
||||
// Minus and Plus buttons
|
||||
p.setPen(colors.outline);
|
||||
|
||||
@@ -205,6 +205,7 @@ void ConfigureProfileManager::AddUser() {
|
||||
|
||||
const auto uuid = Common::UUID::MakeRandom();
|
||||
profile_manager.CreateNewUser(uuid, username.toStdString());
|
||||
profile_manager.WriteUserSaveFile();
|
||||
|
||||
item_model->appendRow(new QStandardItem{GetIcon(uuid), FormatUserEntryText(username, uuid)});
|
||||
}
|
||||
@@ -228,6 +229,7 @@ void ConfigureProfileManager::RenameUser() {
|
||||
std::copy(username_std.begin(), username_std.end(), profile.username.begin());
|
||||
|
||||
profile_manager.SetProfileBase(*uuid, profile);
|
||||
profile_manager.WriteUserSaveFile();
|
||||
|
||||
item_model->setItem(
|
||||
user, 0,
|
||||
@@ -256,6 +258,8 @@ void ConfigureProfileManager::DeleteUser(const Common::UUID& uuid) {
|
||||
return;
|
||||
}
|
||||
|
||||
profile_manager.WriteUserSaveFile();
|
||||
|
||||
item_model->removeRows(tree_view->currentIndex().row(), 1);
|
||||
tree_view->clearSelection();
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ void ConfigureSystem::Setup(const ConfigurationShared::Builder& builder) {
|
||||
}
|
||||
|
||||
if (setting->Id() == Settings::values.region_index.Id()) {
|
||||
// Keep track of the region_index (and langauge_index) combobox to validate the selected
|
||||
// Keep track of the region_index (and language_index) combobox to validate the selected
|
||||
// settings
|
||||
combo_region = widget->combobox;
|
||||
} else if (setting->Id() == Settings::values.language_index.Id()) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/logging/log.h"
|
||||
#include "frontend_common/config.h"
|
||||
#include "yuzu/configuration/input_profiles.h"
|
||||
|
||||
@@ -113,6 +114,8 @@ bool InputProfiles::LoadProfile(const std::string& profile_name, std::size_t pla
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_INFO(Config, "Loading input profile `{}`", profile_name);
|
||||
|
||||
map_profiles[profile_name]->ReadQtControlPlayerValues(player_index);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "input_common/main.h"
|
||||
#include "qt_config.h"
|
||||
#include "uisettings.h"
|
||||
@@ -65,7 +66,7 @@ void QtConfig::ReloadAllValues() {
|
||||
}
|
||||
|
||||
void QtConfig::SaveAllValues() {
|
||||
Save();
|
||||
SaveValues();
|
||||
SaveQtValues();
|
||||
}
|
||||
|
||||
@@ -327,7 +328,10 @@ void QtConfig::ReadMultiplayerValues() {
|
||||
|
||||
void QtConfig::SaveQtValues() {
|
||||
if (global) {
|
||||
LOG_DEBUG(Config, "Saving global Qt configuration values");
|
||||
SaveUIValues();
|
||||
} else {
|
||||
LOG_DEBUG(Config, "Saving Qt configuration values");
|
||||
}
|
||||
SaveQtControlValues();
|
||||
|
||||
@@ -545,6 +549,7 @@ void QtConfig::ReadQtControlPlayerValues(std::size_t player_index) {
|
||||
void QtConfig::SaveQtControlPlayerValues(std::size_t player_index) {
|
||||
BeginGroup(Settings::TranslateCategory(Settings::Category::Controls));
|
||||
|
||||
LOG_DEBUG(Config, "Saving players control configuration values");
|
||||
SavePlayerValues(player_index);
|
||||
SaveQtPlayerValues(player_index);
|
||||
|
||||
|
||||
@@ -750,12 +750,12 @@ Widget::Widget(Settings::BasicSetting* setting_, const TranslationMap& translati
|
||||
}
|
||||
|
||||
apply_funcs.push_back([load_func, setting_](bool powered_on) {
|
||||
if (setting_->RuntimeModfiable() || !powered_on) {
|
||||
if (setting_->RuntimeModifiable() || !powered_on) {
|
||||
load_func();
|
||||
}
|
||||
});
|
||||
|
||||
bool enable = runtime_lock || setting.RuntimeModfiable();
|
||||
bool enable = runtime_lock || setting.RuntimeModifiable();
|
||||
if (setting.Switchable() && Settings::IsConfiguringGlobal() && !runtime_lock) {
|
||||
enable &= setting.UsingGlobal();
|
||||
}
|
||||
|
||||
@@ -206,7 +206,7 @@ void ChatRoom::Initialize(Network::RoomNetwork* room_network_) {
|
||||
room_network = room_network_;
|
||||
// setup the callbacks for network updates
|
||||
if (auto member = room_network->GetRoomMember().lock()) {
|
||||
member->BindOnChatMessageRecieved(
|
||||
member->BindOnChatMessageReceived(
|
||||
[this](const Network::ChatEntry& chat) { emit ChatReceived(chat); });
|
||||
member->BindOnStatusMessageReceived(
|
||||
[this](const Network::StatusMessageEntry& status_message) {
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#define SDL_MAIN_HANDLED
|
||||
#include <SDL.h>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "input_common/main.h"
|
||||
#include "sdl_config.h"
|
||||
|
||||
@@ -64,7 +65,7 @@ void SdlConfig::ReloadAllValues() {
|
||||
}
|
||||
|
||||
void SdlConfig::SaveAllValues() {
|
||||
Save();
|
||||
SaveValues();
|
||||
SaveSdlValues();
|
||||
}
|
||||
|
||||
@@ -177,6 +178,7 @@ void SdlConfig::ReadHidbusValues() {
|
||||
}
|
||||
|
||||
void SdlConfig::SaveSdlValues() {
|
||||
LOG_DEBUG(Config, "Saving SDL configuration values");
|
||||
SaveSdlControlValues();
|
||||
|
||||
WriteToIni();
|
||||
|
||||
@@ -401,7 +401,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (use_multiplayer) {
|
||||
if (auto member = system.GetRoomNetwork().GetRoomMember().lock()) {
|
||||
member->BindOnChatMessageRecieved(OnMessageReceived);
|
||||
member->BindOnChatMessageReceived(OnMessageReceived);
|
||||
member->BindOnStatusMessageReceived(OnStatusMessageReceived);
|
||||
member->BindOnStateChanged(OnStateChanged);
|
||||
member->BindOnError(OnNetworkError);
|
||||
|
||||
Reference in New Issue
Block a user