Compare commits

..

5 Commits

Author SHA1 Message Date
be01af30b8 Android 203 2024-01-22 02:36:04 +00:00
e519d23d9a Merge yuzu-emu#12738 2024-01-22 02:36:03 +00:00
49cbcf5086 Merge yuzu-emu#12736 2024-01-22 02:36:03 +00:00
ce333b7616 Merge yuzu-emu#12579 2024-01-22 02:36:03 +00:00
ccc432ec1c Merge yuzu-emu#12499 2024-01-22 02:36:03 +00:00
26 changed files with 121 additions and 352 deletions

View File

@ -155,7 +155,3 @@ License: MIT
Files: externals/gamemode/* Files: externals/gamemode/*
Copyright: Copyright 2017-2019 Feral Interactive Copyright: Copyright 2017-2019 Feral Interactive
License: BSD-3-Clause License: BSD-3-Clause
Files: src/android/app/debug.keystore
Copyright: 2023 yuzu Emulator Project
License: GPL-3.0-or-later

View File

@ -1,7 +1,9 @@
| Pull Request | Commit | Title | Author | Merged? | | Pull Request | Commit | Title | Author | Merged? |
|----|----|----|----|----| |----|----|----|----|----|
| [12499](https://github.com/yuzu-emu/yuzu-android//pull/12499) | [`fc30a84fc`](https://github.com/yuzu-emu/yuzu-android//pull/12499/files) | Rework time services | [Kelebek1](https://github.com/Kelebek1/) | Yes | | [12499](https://github.com/yuzu-emu/yuzu-android//pull/12499) | [`d95af76e7`](https://github.com/yuzu-emu/yuzu-android//pull/12499/files) | Rework time services | [Kelebek1](https://github.com/Kelebek1/) | Yes |
| [12749](https://github.com/yuzu-emu/yuzu-android//pull/12749) | [`e3171486d`](https://github.com/yuzu-emu/yuzu-android//pull/12749/files) | general: workarounds for SMMU syncing issues | [liamwhite](https://github.com/liamwhite/) | Yes | | [12579](https://github.com/yuzu-emu/yuzu-android//pull/12579) | [`748465f5a`](https://github.com/yuzu-emu/yuzu-android//pull/12579/files) | Core: Implement Device Mapping & GPU SMMU | [FernandoS27](https://github.com/FernandoS27/) | Yes |
| [12736](https://github.com/yuzu-emu/yuzu-android//pull/12736) | [`961b5586a`](https://github.com/yuzu-emu/yuzu-android//pull/12736/files) | android: Add verify contents buttons | [t895](https://github.com/t895/) | Yes |
| [12738](https://github.com/yuzu-emu/yuzu-android//pull/12738) | [`3a25a217e`](https://github.com/yuzu-emu/yuzu-android//pull/12738/files) | android: Port "Lock drawer" feature from Citra | [t895](https://github.com/t895/) | Yes |
End of merge log. You can find the original README.md below the break. End of merge log. You can find the original README.md below the break.

View File

@ -82,8 +82,8 @@ android {
} }
val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE") val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE")
signingConfigs {
if (keystoreFile != null) { if (keystoreFile != null) {
signingConfigs {
create("release") { create("release") {
storeFile = file(keystoreFile) storeFile = file(keystoreFile)
storePassword = System.getenv("ANDROID_KEYSTORE_PASS") storePassword = System.getenv("ANDROID_KEYSTORE_PASS")
@ -91,12 +91,6 @@ android {
keyPassword = System.getenv("ANDROID_KEYSTORE_PASS") keyPassword = System.getenv("ANDROID_KEYSTORE_PASS")
} }
} }
create("default") {
storeFile = file("$projectDir/debug.keystore")
storePassword = "android"
keyAlias = "androiddebugkey"
keyPassword = "android"
}
} }
// Define build types, which are orthogonal to product flavors. // Define build types, which are orthogonal to product flavors.
@ -107,7 +101,7 @@ android {
signingConfig = if (keystoreFile != null) { signingConfig = if (keystoreFile != null) {
signingConfigs.getByName("release") signingConfigs.getByName("release")
} else { } else {
signingConfigs.getByName("default") signingConfigs.getByName("debug")
} }
resValue("string", "app_name_suffixed", "yuzu") resValue("string", "app_name_suffixed", "yuzu")
@ -124,7 +118,7 @@ android {
register("relWithDebInfo") { register("relWithDebInfo") {
isDefault = true isDefault = true
resValue("string", "app_name_suffixed", "yuzu Debug Release") resValue("string", "app_name_suffixed", "yuzu Debug Release")
signingConfig = signingConfigs.getByName("default") signingConfig = signingConfigs.getByName("debug")
isMinifyEnabled = true isMinifyEnabled = true
isDebuggable = true isDebuggable = true
proguardFiles( proguardFiles(
@ -139,7 +133,6 @@ android {
// Signed by debug key disallowing distribution on Play Store. // Signed by debug key disallowing distribution on Play Store.
// Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build.
debug { debug {
signingConfig = signingConfigs.getByName("default")
resValue("string", "app_name_suffixed", "yuzu Debug") resValue("string", "app_name_suffixed", "yuzu Debug")
isDebuggable = true isDebuggable = true
isJniDebuggable = true isJniDebuggable = true

Binary file not shown.

View File

@ -3,6 +3,9 @@
package org.yuzu.yuzu_emu.adapters package org.yuzu.yuzu_emu.adapters
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.drawable.LayerDrawable
import android.net.Uri import android.net.Uri
import android.text.TextUtils import android.text.TextUtils
import android.view.LayoutInflater import android.view.LayoutInflater
@ -12,6 +15,10 @@ import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutInfoCompat
import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.content.pm.ShortcutManagerCompat
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.drawable.toDrawable
import androidx.documentfile.provider.DocumentFile import androidx.documentfile.provider.DocumentFile
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
@ -23,6 +30,7 @@ import kotlinx.coroutines.withContext
import org.yuzu.yuzu_emu.HomeNavigationDirections import org.yuzu.yuzu_emu.HomeNavigationDirections
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.databinding.CardGameBinding import org.yuzu.yuzu_emu.databinding.CardGameBinding
import org.yuzu.yuzu_emu.model.Game import org.yuzu.yuzu_emu.model.Game
import org.yuzu.yuzu_emu.model.GamesViewModel import org.yuzu.yuzu_emu.model.GamesViewModel
@ -81,13 +89,36 @@ class GameAdapter(private val activity: AppCompatActivity) :
) )
.apply() .apply()
val openIntent =
Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse(game.path)
}
activity.lifecycleScope.launch { activity.lifecycleScope.launch {
withContext(Dispatchers.IO) { withContext(Dispatchers.IO) {
val layerDrawable = ResourcesCompat.getDrawable(
YuzuApplication.appContext.resources,
R.drawable.shortcut,
null
) as LayerDrawable
layerDrawable.setDrawableByLayerId(
R.id.shortcut_foreground,
GameIconUtils.getGameIcon(activity, game)
.toDrawable(YuzuApplication.appContext.resources)
)
val inset = YuzuApplication.appContext.resources
.getDimensionPixelSize(R.dimen.icon_inset)
layerDrawable.setLayerInset(1, inset, inset, inset, inset)
val shortcut = val shortcut =
ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path) ShortcutInfoCompat.Builder(YuzuApplication.appContext, game.path)
.setShortLabel(game.title) .setShortLabel(game.title)
.setIcon(GameIconUtils.getShortcutIcon(activity, game)) .setIcon(
.setIntent(game.launchIntent) IconCompat.createWithAdaptiveBitmap(
layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
)
)
.setIntent(openIntent)
.build() .build()
ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut) ShortcutManagerCompat.pushDynamicShortcut(YuzuApplication.appContext, shortcut)
} }

View File

@ -4,8 +4,6 @@
package org.yuzu.yuzu_emu.fragments package org.yuzu.yuzu_emu.fragments
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.pm.ShortcutInfo
import android.content.pm.ShortcutManager
import android.os.Bundle import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.view.LayoutInflater import android.view.LayoutInflater
@ -86,24 +84,6 @@ class GamePropertiesFragment : Fragment() {
view.findNavController().popBackStack() view.findNavController().popBackStack()
} }
val shortcutManager = requireActivity().getSystemService(ShortcutManager::class.java)
binding.buttonShortcut.isEnabled = shortcutManager.isRequestPinShortcutSupported
binding.buttonShortcut.setOnClickListener {
viewLifecycleOwner.lifecycleScope.launch {
withContext(Dispatchers.IO) {
val shortcut = ShortcutInfo.Builder(requireContext(), args.game.title)
.setShortLabel(args.game.title)
.setIcon(
GameIconUtils.getShortcutIcon(requireActivity(), args.game)
.toIcon(requireContext())
)
.setIntent(args.game.launchIntent)
.build()
shortcutManager.requestPinShortcut(shortcut, null)
}
}
}
GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen) GameIconUtils.loadGameIcon(args.game, binding.imageGameScreen)
binding.title.text = args.game.title binding.title.text = args.game.title
binding.title.postDelayed( binding.title.postDelayed(

View File

@ -3,7 +3,6 @@
package org.yuzu.yuzu_emu.model package org.yuzu.yuzu_emu.model
import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Parcelable import android.os.Parcelable
import java.util.HashSet import java.util.HashSet
@ -12,7 +11,6 @@ import kotlinx.serialization.Serializable
import org.yuzu.yuzu_emu.NativeLibrary import org.yuzu.yuzu_emu.NativeLibrary
import org.yuzu.yuzu_emu.R import org.yuzu.yuzu_emu.R
import org.yuzu.yuzu_emu.YuzuApplication import org.yuzu.yuzu_emu.YuzuApplication
import org.yuzu.yuzu_emu.activities.EmulationActivity
import org.yuzu.yuzu_emu.utils.DirectoryInitialization import org.yuzu.yuzu_emu.utils.DirectoryInitialization
import org.yuzu.yuzu_emu.utils.FileUtil import org.yuzu.yuzu_emu.utils.FileUtil
import java.time.LocalDateTime import java.time.LocalDateTime
@ -63,12 +61,6 @@ class Game(
val addonDir: String val addonDir: String
get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/" get() = DirectoryInitialization.userDirectory + "/load/" + programIdHex + "/"
val launchIntent: Intent
get() = Intent(YuzuApplication.appContext, EmulationActivity::class.java).apply {
action = Intent.ACTION_VIEW
data = Uri.parse(path)
}
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
if (other !is Game) { if (other !is Game) {
return false return false

View File

@ -5,10 +5,7 @@ package org.yuzu.yuzu_emu.utils
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.graphics.drawable.LayerDrawable
import android.widget.ImageView import android.widget.ImageView
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.drawable.IconCompat
import androidx.core.graphics.drawable.toBitmap import androidx.core.graphics.drawable.toBitmap
import androidx.core.graphics.drawable.toDrawable import androidx.core.graphics.drawable.toDrawable
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
@ -88,22 +85,4 @@ object GameIconUtils {
return imageLoader.execute(request) return imageLoader.execute(request)
.drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888) .drawable!!.toBitmap(config = Bitmap.Config.ARGB_8888)
} }
suspend fun getShortcutIcon(lifecycleOwner: LifecycleOwner, game: Game): IconCompat {
val layerDrawable = ResourcesCompat.getDrawable(
YuzuApplication.appContext.resources,
R.drawable.shortcut,
null
) as LayerDrawable
layerDrawable.setDrawableByLayerId(
R.id.shortcut_foreground,
getGameIcon(lifecycleOwner, game).toDrawable(YuzuApplication.appContext.resources)
)
val inset = YuzuApplication.appContext.resources
.getDimensionPixelSize(R.dimen.icon_inset)
layerDrawable.setLayerInset(1, inset, inset, inset, inset)
return IconCompat.createWithAdaptiveBitmap(
layerDrawable.toBitmap(config = Bitmap.Config.ARGB_8888)
)
}
} }

View File

@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="?attr/colorControlNormal"
android:pathData="M280,920q-33,0 -56.5,-23.5T200,840v-720q0,-33 23.5,-56.5T280,40h400q33,0 56.5,23.5T760,120v160h-80v-40L280,240v480h400v-40h80v160q0,33 -23.5,56.5T680,920L280,920ZM686,520L480,520v120h-80v-120q0,-33 23.5,-56.5T480,440h206l-62,-64 56,-56 160,160 -160,160 -56,-56 62,-64Z" />
</vector>

View File

@ -43,35 +43,16 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<Button <Button
android:id="@+id/button_back" android:id="@+id/button_back"
style="?attr/materialIconButtonStyle" style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="start"
android:layout_margin="8dp"
app:icon="@drawable/ic_back" app:icon="@drawable/ic_back"
app:iconSize="24dp" app:iconSize="24dp"
app:iconTint="?attr/colorOnSurface" app:iconTint="?attr/colorOnSurface" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_shortcut"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_shortcut"
app:iconSize="24dp"
app:iconTint="?attr/colorOnSurface"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle" style="?attr/materialCardViewElevatedStyle"

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -21,35 +22,16 @@
android:orientation="vertical" android:orientation="vertical"
android:gravity="center_horizontal"> android:gravity="center_horizontal">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
android:orientation="horizontal">
<Button <Button
android:id="@+id/button_back" android:id="@+id/button_back"
style="?attr/materialIconButtonStyle" style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="8dp"
android:layout_gravity="start"
app:icon="@drawable/ic_back" app:icon="@drawable/ic_back"
app:iconSize="24dp" app:iconSize="24dp"
app:iconTint="?attr/colorOnSurface" app:iconTint="?attr/colorOnSurface" />
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/button_shortcut"
style="?attr/materialIconButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:icon="@drawable/ic_shortcut"
app:iconSize="24dp"
app:iconTint="?attr/colorOnSurface"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
<com.google.android.material.card.MaterialCardView <com.google.android.material.card.MaterialCardView
style="?attr/materialCardViewElevatedStyle" style="?attr/materialCardViewElevatedStyle"
@ -63,7 +45,7 @@
android:id="@+id/image_game_screen" android:id="@+id/image_game_screen"
android:layout_width="175dp" android:layout_width="175dp"
android:layout_height="175dp" android:layout_height="175dp"
tools:src="@drawable/default_icon" /> tools:src="@drawable/default_icon"/>
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>

View File

@ -106,7 +106,6 @@ add_library(common STATIC
precompiled_headers.h precompiled_headers.h
quaternion.h quaternion.h
range_map.h range_map.h
range_mutex.h
reader_writer_queue.h reader_writer_queue.h
ring_buffer.h ring_buffer.h
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp ${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp

View File

@ -1,93 +0,0 @@
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <condition_variable>
#include <mutex>
#include "common/intrusive_list.h"
namespace Common {
class ScopedRangeLock;
class RangeMutex {
public:
explicit RangeMutex() = default;
~RangeMutex() = default;
private:
friend class ScopedRangeLock;
void Lock(ScopedRangeLock& l);
void Unlock(ScopedRangeLock& l);
bool HasIntersectionLocked(ScopedRangeLock& l);
private:
std::mutex m_mutex;
std::condition_variable m_cv;
using LockList = Common::IntrusiveListBaseTraits<ScopedRangeLock>::ListType;
LockList m_list;
};
class ScopedRangeLock : public Common::IntrusiveListBaseNode<ScopedRangeLock> {
public:
explicit ScopedRangeLock(RangeMutex& mutex, u64 address, u64 size)
: m_mutex(mutex), m_address(address), m_size(size) {
if (m_size > 0) {
m_mutex.Lock(*this);
}
}
~ScopedRangeLock() {
if (m_size > 0) {
m_mutex.Unlock(*this);
}
}
u64 GetAddress() const {
return m_address;
}
u64 GetSize() const {
return m_size;
}
private:
RangeMutex& m_mutex;
const u64 m_address{};
const u64 m_size{};
};
inline void RangeMutex::Lock(ScopedRangeLock& l) {
std::unique_lock lk{m_mutex};
m_cv.wait(lk, [&] { return !HasIntersectionLocked(l); });
m_list.push_back(l);
}
inline void RangeMutex::Unlock(ScopedRangeLock& l) {
{
std::scoped_lock lk{m_mutex};
m_list.erase(m_list.iterator_to(l));
}
m_cv.notify_all();
}
inline bool RangeMutex::HasIntersectionLocked(ScopedRangeLock& l) {
const auto cur_begin = l.GetAddress();
const auto cur_last = l.GetAddress() + l.GetSize() - 1;
for (const auto& other : m_list) {
const auto other_begin = other.GetAddress();
const auto other_last = other.GetAddress() + other.GetSize() - 1;
if (cur_begin <= other_last && other_begin <= cur_last) {
return true;
}
}
return false;
}
} // namespace Common

View File

@ -420,15 +420,8 @@ struct Values {
SwitchableSetting<s64> custom_rtc{ SwitchableSetting<s64> custom_rtc{
linkage, 0, "custom_rtc", Category::System, Specialization::Time, linkage, 0, "custom_rtc", Category::System, Specialization::Time,
false, true, &custom_rtc_enabled}; false, true, &custom_rtc_enabled};
SwitchableSetting<s64, true> custom_rtc_offset{linkage, SwitchableSetting<s64, false> custom_rtc_offset{
0, linkage, 0, "custom_rtc_offset", Category::System, Specialization::Countable, true, true};
std::numeric_limits<int>::min(),
std::numeric_limits<int>::max(),
"custom_rtc_offset",
Category::System,
Specialization::Countable,
true,
true};
SwitchableSetting<bool> rng_seed_enabled{ SwitchableSetting<bool> rng_seed_enabled{
linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true}; linkage, false, "rng_seed_enabled", Category::System, Specialization::Paired, true, true};
SwitchableSetting<u32> rng_seed{ SwitchableSetting<u32> rng_seed{

View File

@ -10,7 +10,6 @@
#include <mutex> #include <mutex>
#include "common/common_types.h" #include "common/common_types.h"
#include "common/range_mutex.h"
#include "common/scratch_buffer.h" #include "common/scratch_buffer.h"
#include "common/virtual_buffer.h" #include "common/virtual_buffer.h"
@ -205,7 +204,7 @@ private:
(1ULL << (device_virtual_bits - page_bits)) / subentries; (1ULL << (device_virtual_bits - page_bits)) / subentries;
using CachedPages = std::array<CounterEntry, num_counter_entries>; using CachedPages = std::array<CounterEntry, num_counter_entries>;
std::unique_ptr<CachedPages> cached_pages; std::unique_ptr<CachedPages> cached_pages;
Common::RangeMutex counter_guard; std::mutex counter_guard;
std::mutex mapping_guard; std::mutex mapping_guard;
}; };

View File

@ -31,8 +31,9 @@ public:
buffer.resize(0); buffer.resize(0);
size_t index = 0; size_t index = 0;
const auto add_value = [&](u32 value) { const auto add_value = [&](u32 value) {
buffer.resize(index + 1); buffer[index] = value;
buffer[index++] = value; index++;
buffer.resize(index);
}; };
u32 iter_entry = start_entry; u32 iter_entry = start_entry;
@ -508,7 +509,12 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(Asid asid) {
template <typename Traits> template <typename Traits>
void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) {
Common::ScopedRangeLock lk(counter_guard, addr, size); std::unique_lock<std::mutex> lk(counter_guard, std::defer_lock);
const auto Lock = [&] {
if (!lk) {
lk.lock();
}
};
u64 uncache_begin = 0; u64 uncache_begin = 0;
u64 cache_begin = 0; u64 cache_begin = 0;
u64 uncache_bytes = 0; u64 uncache_bytes = 0;
@ -543,6 +549,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
} }
uncache_bytes += Memory::YUZU_PAGESIZE; uncache_bytes += Memory::YUZU_PAGESIZE;
} else if (uncache_bytes > 0) { } else if (uncache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS,
uncache_bytes, false); uncache_bytes, false);
uncache_bytes = 0; uncache_bytes = 0;
@ -553,6 +560,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
} }
cache_bytes += Memory::YUZU_PAGESIZE; cache_bytes += Memory::YUZU_PAGESIZE;
} else if (cache_bytes > 0) { } else if (cache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
true); true);
cache_bytes = 0; cache_bytes = 0;
@ -560,10 +568,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size
vpage++; vpage++;
} }
if (uncache_bytes > 0) { if (uncache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, MarkRegionCaching(memory_device_inter, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes,
false); false);
} }
if (cache_bytes > 0) { if (cache_bytes > 0) {
Lock();
MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, MarkRegionCaching(memory_device_inter, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes,
true); true);
} }

View File

@ -67,29 +67,25 @@ constexpr std::array<SystemArchiveDescriptor, SYSTEM_ARCHIVE_COUNT> SYSTEM_ARCHI
}}; }};
VirtualFile SynthesizeSystemArchive(const u64 title_id) { VirtualFile SynthesizeSystemArchive(const u64 title_id) {
if (title_id < SYSTEM_ARCHIVES.front().title_id || title_id > SYSTEM_ARCHIVES.back().title_id) { if (title_id < SYSTEM_ARCHIVES.front().title_id || title_id > SYSTEM_ARCHIVES.back().title_id)
return nullptr; return nullptr;
}
const auto& desc = SYSTEM_ARCHIVES[title_id - SYSTEM_ARCHIVE_BASE_TITLE_ID]; const auto& desc = SYSTEM_ARCHIVES[title_id - SYSTEM_ARCHIVE_BASE_TITLE_ID];
LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, desc.title_id); LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, desc.title_id);
if (desc.supplier == nullptr) { if (desc.supplier == nullptr)
return nullptr; return nullptr;
}
const auto dir = desc.supplier(); const auto dir = desc.supplier();
if (dir == nullptr) { if (dir == nullptr)
return nullptr; return nullptr;
}
const auto romfs = CreateRomFS(dir); const auto romfs = CreateRomFS(dir);
if (romfs == nullptr) { if (romfs == nullptr)
return nullptr; return nullptr;
}
LOG_INFO(Service_FS, " - System archive generation successful!"); LOG_INFO(Service_FS, " - System archive generation successful!");
return romfs; return romfs;

View File

@ -89,8 +89,7 @@ Service::PSC::Time::LocationName GetTimeZoneString(Service::PSC::Time::LocationN
std::min(configured_name.name.size(), configured_zone.size())); std::min(configured_name.name.size(), configured_zone.size()));
} }
ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone {}!", ASSERT_MSG(IsTimeZoneBinaryValid(configured_name), "Invalid time zone!");
configured_name.name.data());
return configured_name; return configured_name;
} }

View File

@ -61,16 +61,6 @@ Result MountTimeZoneBinary(Core::System& system) {
g_time_zone_binary_romfs = FileSys::ExtractRomFS(nca->GetRomFS()); g_time_zone_binary_romfs = FileSys::ExtractRomFS(nca->GetRomFS());
} }
if (g_time_zone_binary_romfs) {
// Validate that the romfs is readable, using invalid firmware keys can cause this to get
// set but the files to be garbage. In that case, we want to hit the next path and
// synthesise them instead.
Service::PSC::Time::LocationName name{"Etc/GMT"};
if (!IsTimeZoneBinaryValid(name)) {
ResetTimeZoneBinary();
}
}
if (!g_time_zone_binary_romfs) { if (!g_time_zone_binary_romfs) {
g_time_zone_binary_romfs = FileSys::ExtractRomFS( g_time_zone_binary_romfs = FileSys::ExtractRomFS(
FileSys::SystemArchive::SynthesizeSystemArchive(TimeZoneBinaryId)); FileSys::SystemArchive::SynthesizeSystemArchive(TimeZoneBinaryId));
@ -112,7 +102,6 @@ bool IsTimeZoneBinaryValid(Service::PSC::Time::LocationName& name) {
auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)}; auto vfs_file{g_time_zone_binary_romfs->GetFileRelative(path)};
if (!vfs_file) { if (!vfs_file) {
LOG_INFO(Service_Time, "Could not find timezone file {}", path);
return false; return false;
} }
return vfs_file->GetSize() != 0; return vfs_file->GetSize() != 0;

View File

@ -119,21 +119,15 @@ void ServiceManager::Handle_GetStaticServiceAsServiceManager(HLERequestContext&
void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) { void ServiceManager::Handle_SetupStandardSteadyClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called."); LOG_DEBUG(Service_Time, "called.");
struct Parameters {
bool reset_detected;
Common::UUID clock_source_id;
s64 rtc_offset;
s64 internal_offset;
s64 test_offset;
};
static_assert(sizeof(Parameters) == 0x30);
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
auto params{rp.PopRaw<Parameters>()}; auto clock_source_id{rp.PopRaw<Common::UUID>()};
auto rtc_offset{rp.Pop<s64>()};
auto internal_offset{rp.Pop<s64>()};
auto test_offset{rp.Pop<s64>()};
auto is_rtc_reset_detected{rp.Pop<bool>()};
auto res = SetupStandardSteadyClockCore(params.clock_source_id, params.rtc_offset, auto res = SetupStandardSteadyClockCore(clock_source_id, rtc_offset, internal_offset,
params.internal_offset, params.test_offset, test_offset, is_rtc_reset_detected);
params.reset_detected);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res);
@ -168,16 +162,11 @@ void ServiceManager::Handle_SetupStandardNetworkSystemClockCore(HLERequestContex
void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) { void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called."); LOG_DEBUG(Service_Time, "called.");
struct Parameters {
bool automatic_correction;
SteadyClockTimePoint time_point;
};
static_assert(sizeof(Parameters) == 0x20);
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
auto params{rp.PopRaw<Parameters>()}; auto time_point{rp.PopRaw<SteadyClockTimePoint>()};
auto automatic_correction{rp.Pop<bool>()};
auto res = SetupStandardUserSystemClockCore(params.time_point, params.automatic_correction); auto res = SetupStandardUserSystemClockCore(time_point, automatic_correction);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res);
@ -186,21 +175,16 @@ void ServiceManager::Handle_SetupStandardUserSystemClockCore(HLERequestContext&
void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) { void ServiceManager::Handle_SetupTimeZoneServiceCore(HLERequestContext& ctx) {
LOG_DEBUG(Service_Time, "called."); LOG_DEBUG(Service_Time, "called.");
struct Parameters {
u32 location_count;
LocationName name;
SteadyClockTimePoint time_point;
RuleVersion rule_version;
};
static_assert(sizeof(Parameters) == 0x50);
IPC::RequestParser rp{ctx}; IPC::RequestParser rp{ctx};
auto params{rp.PopRaw<Parameters>()}; auto name{rp.PopRaw<LocationName>()};
auto time_point{rp.PopRaw<SteadyClockTimePoint>()};
auto rule_version{rp.PopRaw<RuleVersion>()};
auto location_count{rp.Pop<u32>()};
auto rule_buffer{ctx.ReadBuffer()}; auto rule_buffer{ctx.ReadBuffer()};
auto res = SetupTimeZoneServiceCore(params.name, params.time_point, params.rule_version, auto res =
params.location_count, rule_buffer); SetupTimeZoneServiceCore(name, time_point, rule_version, location_count, rule_buffer);
IPC::ResponseBuilder rb{ctx, 2}; IPC::ResponseBuilder rb{ctx, 2};
rb.Push(res); rb.Push(res);
@ -302,22 +286,11 @@ void ServiceManager::Handle_GetClosestAlarmInfo(HLERequestContext& ctx) {
s64 time{}; s64 time{};
auto res = GetClosestAlarmInfo(is_valid, alarm_info, time); auto res = GetClosestAlarmInfo(is_valid, alarm_info, time);
struct OutParameters { IPC::ResponseBuilder rb{ctx, 5 + sizeof(AlarmInfo) / sizeof(u32)};
bool is_valid;
AlarmInfo alarm_info;
s64 time;
};
static_assert(sizeof(OutParameters) == 0x20);
OutParameters out_params{
.is_valid = is_valid,
.alarm_info = alarm_info,
.time = time,
};
IPC::ResponseBuilder rb{ctx, 2 + sizeof(OutParameters) / sizeof(u32)};
rb.Push(res); rb.Push(res);
rb.PushRaw<OutParameters>(out_params); rb.PushRaw<AlarmInfo>(alarm_info);
rb.Push<bool>(is_valid);
rb.Push<s64>(time);
} }
// =============================== Implementations =========================== // =============================== Implementations ===========================

View File

@ -15,12 +15,12 @@ SteadyClock::SteadyClock(Core::System& system_, std::shared_ptr<TimeManager> man
// clang-format off // clang-format off
static const FunctionInfo functions[] = { static const FunctionInfo functions[] = {
{0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"}, {0, &SteadyClock::Handle_GetCurrentTimePoint, "GetCurrentTimePoint"},
{2, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"}, {1, &SteadyClock::Handle_GetTestOffset, "GetTestOffset"},
{3, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"}, {2, &SteadyClock::Handle_SetTestOffset, "SetTestOffset"},
{100, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"}, {3, &SteadyClock::Handle_GetRtcValue, "GetRtcValue"},
{101, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"}, {4, &SteadyClock::Handle_IsRtcResetDetected, "IsRtcResetDetected"},
{102, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"}, {5, &SteadyClock::Handle_GetSetupResultValue, "GetSetupResultValue"},
{200, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"}, {6, &SteadyClock::Handle_GetInternalOffset, "GetInternalOffset"},
}; };
// clang-format on // clang-format on
RegisterHandlers(functions); RegisterHandlers(functions);

View File

@ -1093,20 +1093,6 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) {
[&] { rasterizer = true; }); [&] { rasterizer = true; });
if (rasterizer) { if (rasterizer) {
impl->InvalidateGPUMemory(ptr, size); impl->InvalidateGPUMemory(ptr, size);
const auto type = impl->current_page_table->pointers[vaddr >> YUZU_PAGEBITS].Type();
if (type == Common::PageType::RasterizerCachedMemory) {
// Check if device mapped. If not, this bugged and we can unmark.
DAddr addr{};
Common::ScratchBuffer<u32> buffer;
impl->gpu_device_memory->ApplyOpOnPointer(ptr, buffer,
[&](DAddr address) { addr = address; });
if (addr == 0) {
LOG_ERROR(HW_Memory, "Fixing unmapped cached region {:#x}", GetInteger(vaddr));
impl->RasterizerMarkRegionCached(GetInteger(vaddr), size, false);
}
}
} }
#ifdef __linux__ #ifdef __linux__

View File

@ -1546,10 +1546,7 @@ void BufferCache<P>::ImmediateUploadMemory([[maybe_unused]] Buffer& buffer,
std::span<const u8> upload_span; std::span<const u8> upload_span;
const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset; const DAddr device_addr = buffer.CpuAddr() + copy.dst_offset;
if (IsRangeGranular(device_addr, copy.size)) { if (IsRangeGranular(device_addr, copy.size)) {
auto* const ptr = device_memory.GetPointer<u8>(device_addr); upload_span = std::span(device_memory.GetPointer<u8>(device_addr), copy.size);
if (ptr != nullptr) {
upload_span = std::span(ptr, copy.size);
}
} else { } else {
if (immediate_buffer.empty()) { if (immediate_buffer.empty()) {
immediate_buffer = ImmediateBuffer(largest_copy); immediate_buffer = ImmediateBuffer(largest_copy);

View File

@ -243,12 +243,10 @@ void RendererOpenGL::LoadFBToScreenInfo(const Tegra::FramebufferConfig& framebuf
const u64 size_in_bytes{Tegra::Texture::CalculateSize( const u64 size_in_bytes{Tegra::Texture::CalculateSize(
true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)}; true, bytes_per_pixel, framebuffer.stride, framebuffer.height, 1, block_height_log2, 0)};
const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)}; const u8* const host_ptr{device_memory.GetPointer<u8>(framebuffer_addr)};
if (host_ptr != nullptr) {
const std::span<const u8> input_data(host_ptr, size_in_bytes); const std::span<const u8> input_data(host_ptr, size_in_bytes);
Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel, Tegra::Texture::UnswizzleTexture(gl_framebuffer_data, input_data, bytes_per_pixel,
framebuffer.width, framebuffer.height, 1, framebuffer.width, framebuffer.height, 1, block_height_log2,
block_height_log2, 0); 0);
}
glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride)); glPixelStorei(GL_UNPACK_ROW_LENGTH, static_cast<GLint>(framebuffer.stride));

View File

@ -230,11 +230,9 @@ void BlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel, const u64 tiled_size{Tegra::Texture::CalculateSize(true, bytes_per_pixel,
framebuffer.stride, framebuffer.height, framebuffer.stride, framebuffer.height,
1, block_height_log2, 0)}; 1, block_height_log2, 0)};
if (host_ptr != nullptr) {
Tegra::Texture::UnswizzleTexture( Tegra::Texture::UnswizzleTexture(
mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size), mapped_span.subspan(image_offset, linear_size), std::span(host_ptr, tiled_size),
bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0); bytes_per_pixel, framebuffer.width, framebuffer.height, 1, block_height_log2, 0);
}
const VkBufferImageCopy copy{ const VkBufferImageCopy copy{
.bufferOffset = image_offset, .bufferOffset = image_offset,

View File

@ -1064,6 +1064,8 @@ public:
} }
}); });
} }
auto* ptr = device_memory.GetPointer<u8>(new_query->dependant_address);
ASSERT(ptr != nullptr);
new_query->dependant_manage = must_manage_dependance; new_query->dependant_manage = must_manage_dependance;
pending_flush_queries.push_back(index); pending_flush_queries.push_back(index);
@ -1102,12 +1104,10 @@ public:
tfb_streamer.Free(query->dependant_index); tfb_streamer.Free(query->dependant_index);
} else { } else {
u8* pointer = device_memory.GetPointer<u8>(query->dependant_address); u8* pointer = device_memory.GetPointer<u8>(query->dependant_address);
if (pointer != nullptr) {
u32 result; u32 result;
std::memcpy(&result, pointer, sizeof(u32)); std::memcpy(&result, pointer, sizeof(u32));
num_vertices = static_cast<u64>(result) / query->stride; num_vertices = static_cast<u64>(result) / query->stride;
} }
}
query->value = [&]() -> u64 { query->value = [&]() -> u64 {
switch (query->topology) { switch (query->topology) {
case Maxwell3D::Regs::PrimitiveTopology::Points: case Maxwell3D::Regs::PrimitiveTopology::Points:
@ -1360,9 +1360,7 @@ bool QueryCacheRuntime::HostConditionalRenderingCompareValues(VideoCommon::Looku
const auto check_value = [&](DAddr address) { const auto check_value = [&](DAddr address) {
u8* ptr = impl->device_memory.GetPointer<u8>(address); u8* ptr = impl->device_memory.GetPointer<u8>(address);
u64 value{}; u64 value{};
if (ptr != nullptr) {
std::memcpy(&value, ptr, sizeof(value)); std::memcpy(&value, ptr, sizeof(value));
}
return value == 0; return value == 0;
}; };
std::array<VideoCommon::LookupData*, 2> objects{&object_1, &object_2}; std::array<VideoCommon::LookupData*, 2> objects{&object_1, &object_2};