mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-18 06:10:35 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 03ac968ca7 |
@@ -2,6 +2,8 @@
|
|||||||
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
# SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
# SPDX-FileCopyrightText: 2018 yuzu Emulator Project
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
-->
|
-->
|
||||||
|
|||||||
Vendored
+1
-3
@@ -804,9 +804,7 @@ Particles tend to only render correctly with Accurate mode.</source>
|
|||||||
<source>Controls the DMA read mode.
|
<source>Controls the DMA read mode.
|
||||||
Unsafe is faster, while Safe is more stable and can fix issues in some games.
|
Unsafe is faster, while Safe is more stable and can fix issues in some games.
|
||||||
Default follows the GPU Accuracy setting.</source>
|
Default follows the GPU Accuracy setting.</source>
|
||||||
<translation>Controla el modo de lectura DMA.
|
<translation type="unfinished"/>
|
||||||
Inseguro es más rápido, mientras que seguro es más estable y puede solucionar fallos en algunos juegos.
|
|
||||||
Predeterminado sigue el ajuste de la precisión de GPU.</translation>
|
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="227"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="227"/>
|
||||||
|
|||||||
Vendored
+1
-3
@@ -793,9 +793,7 @@ Safe to set at 16x on most GPUs.</source>
|
|||||||
<source>Controls the GPU emulation mode.
|
<source>Controls the GPU emulation mode.
|
||||||
Most games render fine with Fast, but Accurate is still required for some.
|
Most games render fine with Fast, but Accurate is still required for some.
|
||||||
Particles tend to only render correctly with Accurate mode.</source>
|
Particles tend to only render correctly with Accurate mode.</source>
|
||||||
<translation>Керує режимом емуляції ГП.
|
<translation type="unfinished"/>
|
||||||
Більшість ігор добре візуалізуються з режимом «Швидко», але деякі ігри можуть потребувати режиму «Точно».
|
|
||||||
Частинки зазвичай правильно візуалізуються лише з режимом «Точно».</translation>
|
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../../src/qt_common/config/shared_translation.cpp" line="225"/>
|
<location filename="../../src/qt_common/config/shared_translation.cpp" line="225"/>
|
||||||
|
|||||||
@@ -27,6 +27,3 @@ There are two main applications, an SDL-based app (`eden-cli`) and a Qt based ap
|
|||||||
- `--user/-u`: Specify the user index.
|
- `--user/-u`: Specify the user index.
|
||||||
- `--version/-v`: Display version and quit.
|
- `--version/-v`: Display version and quit.
|
||||||
- `--input-profile/-i`: Specifies input profile name to use (for player #0 only).
|
- `--input-profile/-i`: Specifies input profile name to use (for player #0 only).
|
||||||
- `--null-render/-n`: Forces the usage of the "Null" render backend irrespective of settings.
|
|
||||||
- `--filter/-x`: Sets the debug log filter irrespective of settings.
|
|
||||||
- `--singlecore/-s`: Forces single-core regardless of settings.
|
|
||||||
|
|||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: 2024 yuzu Emulator Project
|
||||||
@@ -169,7 +169,7 @@ class InputDialogFragment : DialogFragment() {
|
|||||||
NativeInput.onGamePadButtonEvent(
|
NativeInput.onGamePadButtonEvent(
|
||||||
controllerData.getGUID(),
|
controllerData.getGUID(),
|
||||||
controllerData.getPort(),
|
controllerData.getPort(),
|
||||||
InputHandler.getButtonIdFromEvent(event),
|
event.keyCode,
|
||||||
action
|
action
|
||||||
)
|
)
|
||||||
onInputReceived(event.device)
|
onInputReceived(event.device)
|
||||||
|
|||||||
@@ -49,12 +49,6 @@ object InputHandler {
|
|||||||
MotionEvent.AXIS_RTRIGGER
|
MotionEvent.AXIS_RTRIGGER
|
||||||
)
|
)
|
||||||
|
|
||||||
// Currently, Android doesn't support Joy-Con D-pad buttons. We fall back to the scan code
|
|
||||||
private const val LINUX_BUTTON_DPAD_UP = 0x220
|
|
||||||
private const val LINUX_BUTTON_DPAD_DOWN = 0x221
|
|
||||||
private const val LINUX_BUTTON_DPAD_LEFT = 0x222
|
|
||||||
private const val LINUX_BUTTON_DPAD_RIGHT = 0x223
|
|
||||||
|
|
||||||
fun isPhysicalGameController(device: InputDevice?): Boolean {
|
fun isPhysicalGameController(device: InputDevice?): Boolean {
|
||||||
device ?: return false
|
device ?: return false
|
||||||
|
|
||||||
@@ -93,25 +87,12 @@ object InputHandler {
|
|||||||
NativeInput.onGamePadButtonEvent(
|
NativeInput.onGamePadButtonEvent(
|
||||||
controllerData.getGUID(),
|
controllerData.getGUID(),
|
||||||
controllerData.getPort(),
|
controllerData.getPort(),
|
||||||
getButtonIdFromEvent(event),
|
event.keyCode,
|
||||||
action
|
action
|
||||||
)
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getButtonIdFromEvent(event: KeyEvent): Int {
|
|
||||||
if (event.keyCode == 0) {
|
|
||||||
return when (event.scanCode) {
|
|
||||||
LINUX_BUTTON_DPAD_UP -> KeyEvent.KEYCODE_DPAD_UP
|
|
||||||
LINUX_BUTTON_DPAD_DOWN -> KeyEvent.KEYCODE_DPAD_DOWN
|
|
||||||
LINUX_BUTTON_DPAD_LEFT -> KeyEvent.KEYCODE_DPAD_LEFT
|
|
||||||
LINUX_BUTTON_DPAD_RIGHT -> KeyEvent.KEYCODE_DPAD_RIGHT
|
|
||||||
else -> return 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return event.keyCode
|
|
||||||
}
|
|
||||||
|
|
||||||
fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
fun dispatchGenericMotionEvent(event: MotionEvent): Boolean {
|
||||||
val controllerData =
|
val controllerData =
|
||||||
androidControllers[event.device.controllerNumber] ?: return false
|
androidControllers[event.device.controllerNumber] ?: return false
|
||||||
|
|||||||
@@ -20,96 +20,132 @@ struct RomMetadata {
|
|||||||
std::vector<u8> icon;
|
std::vector<u8> icon;
|
||||||
bool isHomebrew;
|
bool isHomebrew;
|
||||||
};
|
};
|
||||||
static ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
|
|
||||||
|
|
||||||
static RomMetadata CacheRomMetadata(const std::string& path) {
|
ankerl::unordered_dense::map<std::string, RomMetadata> m_rom_metadata_cache;
|
||||||
auto& instance = EmulationSession::GetInstance();
|
|
||||||
const auto file = Core::GetGameFileFromPath(instance.System().GetFilesystem(), path);
|
|
||||||
if (auto loader = Loader::GetLoader(instance.System(), file, 0, 0); loader) {
|
|
||||||
RomMetadata entry;
|
|
||||||
loader->ReadTitle(entry.title);
|
|
||||||
loader->ReadProgramId(entry.programId);
|
|
||||||
loader->ReadIcon(entry.icon);
|
|
||||||
|
|
||||||
const FileSys::PatchManager pm{
|
RomMetadata CacheRomMetadata(const std::string& path) {
|
||||||
entry.programId,
|
const auto file =
|
||||||
instance.System().GetFileSystemController(),
|
Core::GetGameFileFromPath(EmulationSession::GetInstance().System().GetFilesystem(), path);
|
||||||
instance.System().GetContentProvider()
|
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file, 0, 0);
|
||||||
};
|
|
||||||
const auto control = pm.GetControlMetadata();
|
|
||||||
|
|
||||||
if (control.first != nullptr) {
|
RomMetadata entry;
|
||||||
entry.developer = control.first->GetDeveloperName();
|
loader->ReadTitle(entry.title);
|
||||||
entry.version = control.first->GetVersionString();
|
loader->ReadProgramId(entry.programId);
|
||||||
|
loader->ReadIcon(entry.icon);
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm{
|
||||||
|
entry.programId, EmulationSession::GetInstance().System().GetFileSystemController(),
|
||||||
|
EmulationSession::GetInstance().System().GetContentProvider()};
|
||||||
|
const auto control = pm.GetControlMetadata();
|
||||||
|
|
||||||
|
if (control.first != nullptr) {
|
||||||
|
entry.developer = control.first->GetDeveloperName();
|
||||||
|
entry.version = control.first->GetVersionString();
|
||||||
|
} else {
|
||||||
|
FileSys::NACP nacp;
|
||||||
|
if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success) {
|
||||||
|
entry.developer = nacp.GetDeveloperName();
|
||||||
} else {
|
} else {
|
||||||
FileSys::NACP nacp{};
|
entry.developer = "";
|
||||||
entry.developer = loader->ReadControlData(nacp) == Loader::ResultStatus::Success
|
|
||||||
? nacp.GetDeveloperName()
|
|
||||||
: "";
|
|
||||||
entry.version = "1.0.0";
|
|
||||||
}
|
}
|
||||||
if (loader->GetFileType() == Loader::FileType::NRO) {
|
|
||||||
auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
|
entry.version = "1.0.0";
|
||||||
entry.isHomebrew = loader_nro->IsHomebrew();
|
|
||||||
} else {
|
|
||||||
entry.isHomebrew = false;
|
|
||||||
}
|
|
||||||
m_rom_metadata_cache[path] = entry;
|
|
||||||
return entry;
|
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
|
if (loader->GetFileType() == Loader::FileType::NRO) {
|
||||||
|
auto loader_nro = reinterpret_cast<Loader::AppLoader_NRO*>(loader.get());
|
||||||
|
entry.isHomebrew = loader_nro->IsHomebrew();
|
||||||
|
} else {
|
||||||
|
entry.isHomebrew = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rom_metadata_cache[path] = entry;
|
||||||
|
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
static RomMetadata GetRomMetadata(const std::string& path, bool reload = false) {
|
RomMetadata GetRomMetadata(const std::string& path, bool reload = false) {
|
||||||
if (reload)
|
if (reload) {
|
||||||
return CacheRomMetadata(path);
|
return CacheRomMetadata(path);
|
||||||
if (auto it = m_rom_metadata_cache.find(path); it != m_rom_metadata_cache.end())
|
}
|
||||||
return it->second;
|
|
||||||
|
if (auto search = m_rom_metadata_cache.find(path); search != m_rom_metadata_cache.end()) {
|
||||||
|
return search->second;
|
||||||
|
}
|
||||||
|
|
||||||
return CacheRomMetadata(path);
|
return CacheRomMetadata(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj, jstring jpath) {
|
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsValid(JNIEnv* env, jobject obj,
|
||||||
if (auto const file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read); file) {
|
jstring jpath) {
|
||||||
if (auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file); loader) {
|
const auto file = EmulationSession::GetInstance().System().GetFilesystem()->OpenFile(
|
||||||
auto const file_type = loader->GetFileType();
|
Common::Android::GetJString(env, jpath), FileSys::OpenMode::Read);
|
||||||
if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error)
|
if (!file) {
|
||||||
return false;
|
return false;
|
||||||
if ((file_type == Loader::FileType::NSP || file_type == Loader::FileType::XCI) && !Loader::IsBootableGameContainer(file, file_type))
|
|
||||||
return false;
|
|
||||||
u64 program_id = 0;
|
|
||||||
return loader->ReadProgramId(program_id) == Loader::ResultStatus::Success;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
auto loader = Loader::GetLoader(EmulationSession::GetInstance().System(), file);
|
||||||
|
if (!loader) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto file_type = loader->GetFileType();
|
||||||
|
if (file_type == Loader::FileType::Unknown || file_type == Loader::FileType::Error) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((file_type == Loader::FileType::NSP || file_type == Loader::FileType::XCI) &&
|
||||||
|
!Loader::IsBootableGameContainer(file, file_type)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 program_id = 0;
|
||||||
|
Loader::ResultStatus res = loader->ReadProgramId(program_id);
|
||||||
|
if (res != Loader::ResultStatus::Success) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj, jstring jpath) {
|
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getTitle(JNIEnv* env, jobject obj,
|
||||||
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title);
|
jstring jpath) {
|
||||||
|
return Common::Android::ToJString(
|
||||||
|
env, GetRomMetadata(Common::Android::GetJString(env, jpath)).title);
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj, jstring jpath) {
|
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getProgramId(JNIEnv* env, jobject obj,
|
||||||
return Common::Android::ToJString(env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId));
|
jstring jpath) {
|
||||||
|
return Common::Android::ToJString(
|
||||||
|
env, std::to_string(GetRomMetadata(Common::Android::GetJString(env, jpath)).programId));
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj, jstring jpath) {
|
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getDeveloper(JNIEnv* env, jobject obj,
|
||||||
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer);
|
jstring jpath) {
|
||||||
|
return Common::Android::ToJString(
|
||||||
|
env, GetRomMetadata(Common::Android::GetJString(env, jpath)).developer);
|
||||||
}
|
}
|
||||||
|
|
||||||
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj, jstring jpath, jboolean jreload) {
|
jstring Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getVersion(JNIEnv* env, jobject obj,
|
||||||
return Common::Android::ToJString(env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version);
|
jstring jpath, jboolean jreload) {
|
||||||
|
return Common::Android::ToJString(
|
||||||
|
env, GetRomMetadata(Common::Android::GetJString(env, jpath), jreload).version);
|
||||||
}
|
}
|
||||||
|
|
||||||
jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj, jstring jpath) {
|
jbyteArray Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIcon(JNIEnv* env, jobject obj,
|
||||||
|
jstring jpath) {
|
||||||
auto icon_data = GetRomMetadata(Common::Android::GetJString(env, jpath)).icon;
|
auto icon_data = GetRomMetadata(Common::Android::GetJString(env, jpath)).icon;
|
||||||
jbyteArray icon = env->NewByteArray(jsize(icon_data.size()));
|
jbyteArray icon = env->NewByteArray(static_cast<jsize>(icon_data.size()));
|
||||||
env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon), reinterpret_cast<jbyte*>(icon_data.data()));
|
env->SetByteArrayRegion(icon, 0, env->GetArrayLength(icon),
|
||||||
|
reinterpret_cast<jbyte*>(icon_data.data()));
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj, jstring jpath) {
|
jboolean Java_org_yuzu_yuzu_1emu_utils_GameMetadata_getIsHomebrew(JNIEnv* env, jobject obj,
|
||||||
return jboolean(GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew);
|
jstring jpath) {
|
||||||
|
return static_cast<jboolean>(
|
||||||
|
GetRomMetadata(Common::Android::GetJString(env, jpath)).isHomebrew);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) {
|
void Java_org_yuzu_yuzu_1emu_utils_GameMetadata_resetMetadata(JNIEnv* env, jobject obj) {
|
||||||
|
|||||||
@@ -473,7 +473,7 @@
|
|||||||
<string name="advanced">متقدم</string>
|
<string name="advanced">متقدم</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">وضع وحدة معالجة الرسومات</string>
|
<string name="renderer_accuracy">وضع وحدة معالجة الرسومات</string>
|
||||||
<string name="renderer_accuracy_description">يتحكم هذا الخيار في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع الوضع السريع، لكن الوضع الدقيق لا يزال ضروريًا لبعضها. تميل الجسيمات إلى الظهور بشكل صحيح فقط مع الوضع الدقيق.</string>
|
<string name="renderer_accuracy_description">يتحكم في وضع محاكاة وحدة معالجة الرسومات. تعمل معظم الألعاب بشكل جيد مع وضعي سريع أو متوازن، لكن الوضع الدقيق لا يزال مطلوبًا لبعض الألعاب. تميل الجسيمات إلى العرض بشكل صحيح فقط عند استخدام الوضع الدقيق.</string>
|
||||||
<string name="dma_accuracy">دقة DMA</string>
|
<string name="dma_accuracy">دقة DMA</string>
|
||||||
<string name="dma_accuracy_description">يتحكم في دقة DMA. يمكن أن تؤدي الدقة الآمنة إلى حل المشكلات في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا لم تكن متأكدًا، فاترك هذا الخيار على الإعداد الافتراضي.</string>
|
<string name="dma_accuracy_description">يتحكم في دقة DMA. يمكن أن تؤدي الدقة الآمنة إلى حل المشكلات في بعض الألعاب، ولكنها قد تؤثر أيضًا على الأداء في بعض الحالات. إذا لم تكن متأكدًا، فاترك هذا الخيار على الإعداد الافتراضي.</string>
|
||||||
<string name="gpu_fence_behavior">سلوك حاجز وحدة معالجة الرسومات</string>
|
<string name="gpu_fence_behavior">سلوك حاجز وحدة معالجة الرسومات</string>
|
||||||
|
|||||||
@@ -445,6 +445,7 @@
|
|||||||
<string name="advanced">Pokročilé</string>
|
<string name="advanced">Pokročilé</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">Režim GPU</string>
|
<string name="renderer_accuracy">Režim GPU</string>
|
||||||
|
<string name="renderer_accuracy_description">Určuje režim emulovaného GPU. Většina her běží bez problémů v rychlém, nebo vyváženém režimu, ale některé stále vyžadují přesný režim. Částicové efekty se většinou zobrazují korektně pouze v přesném režimu. </string>
|
||||||
<string name="dma_accuracy">Přesnost DMA</string>
|
<string name="dma_accuracy">Přesnost DMA</string>
|
||||||
<string name="dma_accuracy_description">Ovládá přesnost DMA. Bezpečná přesnost může vyřešit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, použijte výchozí nastavení.</string>
|
<string name="dma_accuracy_description">Ovládá přesnost DMA. Bezpečná přesnost může vyřešit problémy v některých hrách, ale v některých případech může také ovlivnit výkon. Pokud si nejste jisti, použijte výchozí nastavení.</string>
|
||||||
<string name="anisotropic_filtering">Anizotropní filtrování</string>
|
<string name="anisotropic_filtering">Anizotropní filtrování</string>
|
||||||
|
|||||||
@@ -457,6 +457,7 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
|||||||
<string name="advanced">Erweitert</string>
|
<string name="advanced">Erweitert</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">GPU-Modus</string>
|
<string name="renderer_accuracy">GPU-Modus</string>
|
||||||
|
<string name="renderer_accuracy_description">Steuert den GPU-Emulationsmodus. Die meisten Spiele werden im Modus \"Fast\" oder \"Balanced\" gut gerendert, für einige ist jedoch weiterhin der Modus \"Accurate\" erforderlich. Partikel werden in der Regel nur im Modus \"Accurate\" korrekt gerendert.</string>
|
||||||
<string name="dma_accuracy">DMA-Genauigkeit</string>
|
<string name="dma_accuracy">DMA-Genauigkeit</string>
|
||||||
<string name="dma_accuracy_description">Steuert die DMA-Präzisionsgenauigkeit. Sichere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel lassen Sie dies auf Standard stehen.</string>
|
<string name="dma_accuracy_description">Steuert die DMA-Präzisionsgenauigkeit. Sichere Präzision kann Probleme in einigen Spielen beheben, kann aber in einigen Fällen auch die Leistung beeinträchtigen. Im Zweifel lassen Sie dies auf Standard stehen.</string>
|
||||||
<string name="anisotropic_filtering">Anisotrope Filterung</string>
|
<string name="anisotropic_filtering">Anisotrope Filterung</string>
|
||||||
|
|||||||
@@ -467,6 +467,7 @@
|
|||||||
<string name="advanced">Avanzado</string>
|
<string name="advanced">Avanzado</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">Modo de la GPU</string>
|
<string name="renderer_accuracy">Modo de la GPU</string>
|
||||||
|
<string name="renderer_accuracy_description">Controla el modo de la emulación de la GPU. La mayoría de los juegos se renderizan correctamente en los modos Rápido o Equilibrado, pero algunos requieren Preciso. Las partículas tienden a renderizarse correctamente solo con el modo Preciso.</string>
|
||||||
<string name="dma_accuracy">Precisión de DMA</string>
|
<string name="dma_accuracy">Precisión de DMA</string>
|
||||||
<string name="dma_accuracy_description">Controla la precisión de DMA. La precisión segura puede solucionar problemas en algunos juegos, pero también puede afectar al rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado.</string>
|
<string name="dma_accuracy_description">Controla la precisión de DMA. La precisión segura puede solucionar problemas en algunos juegos, pero también puede afectar al rendimiento en algunos casos. Si no está seguro, déjelo en Predeterminado.</string>
|
||||||
<string name="gpu_fence_behavior">Comportamiento de vallado de la GPU</string>
|
<string name="gpu_fence_behavior">Comportamiento de vallado de la GPU</string>
|
||||||
|
|||||||
@@ -445,6 +445,7 @@
|
|||||||
<string name="advanced">Zaawansowane</string>
|
<string name="advanced">Zaawansowane</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">Tryb GPU</string>
|
<string name="renderer_accuracy">Tryb GPU</string>
|
||||||
|
<string name="renderer_accuracy_description">Steruje trybem emulacji GPU. Większość gier renderuje się poprawnie w trybach Szybki lub Zrównoważony, ale dla niektórych nadal wymagany jest tryb Dokładny. Efekty cząsteczkowe zwykle renderują się poprawnie tylko w trybie Dokładnym.</string>
|
||||||
<string name="dma_accuracy">Dokładność DMA</string>
|
<string name="dma_accuracy">Dokładność DMA</string>
|
||||||
<string name="dma_accuracy_description">Kontroluje dokładność precyzji DMA. Bezpieczna precyzja może naprawić problemy w niektórych grach, ale w niektórych przypadkach może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość Domyślną.</string>
|
<string name="dma_accuracy_description">Kontroluje dokładność precyzji DMA. Bezpieczna precyzja może naprawić problemy w niektórych grach, ale w niektórych przypadkach może również wpłynąć na wydajność. Jeśli nie jesteś pewien, pozostaw wartość Domyślną.</string>
|
||||||
<string name="anisotropic_filtering">Filtrowanie anizotropowe</string>
|
<string name="anisotropic_filtering">Filtrowanie anizotropowe</string>
|
||||||
|
|||||||
@@ -424,9 +424,6 @@
|
|||||||
<string name="cpu_accuracy">Точность ЦП</string>
|
<string name="cpu_accuracy">Точность ЦП</string>
|
||||||
<string name="value_with_units">%1$s%2$s</string>
|
<string name="value_with_units">%1$s%2$s</string>
|
||||||
|
|
||||||
<string name="program_args">Аргументы Homebrew</string>
|
|
||||||
<string name="program_args_description">Аргументы командной строки, переданные Homebrew при запуске (например, -noglsl)</string>
|
|
||||||
|
|
||||||
<!-- System settings strings -->
|
<!-- System settings strings -->
|
||||||
<string name="device_name">Название устройства</string>
|
<string name="device_name">Название устройства</string>
|
||||||
<string name="use_docked_mode">Режим док-станции</string>
|
<string name="use_docked_mode">Режим док-станции</string>
|
||||||
@@ -469,11 +466,9 @@
|
|||||||
<string name="advanced">Расширенные</string>
|
<string name="advanced">Расширенные</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">Режим ГПУ</string>
|
<string name="renderer_accuracy">Режим ГПУ</string>
|
||||||
<string name="renderer_accuracy_description">Управляет режимом эмуляции ГПУ. Большинство игр нормально отображаются в режиме Быстрый, но для некоторых требуется режим Точный. Частицы обычно корректно отображаются только в режиме Точный.</string>
|
<string name="renderer_accuracy_description">Управляет режимом эмуляции графического процессора. Большинство игр нормально отображаются в режимах «Быстрый» или «Сбалансированный», но для некоторых требуется режим «Точный». Частицы обычно корректно отображаются только в режиме «Точный».</string>
|
||||||
<string name="dma_accuracy">Точность DMA</string>
|
<string name="dma_accuracy">Точность DMA</string>
|
||||||
<string name="dma_accuracy_description">Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию.</string>
|
<string name="dma_accuracy_description">Управляет точностью DMA. Безопасная точность может исправить проблемы в некоторых играх, но в некоторых случаях также может повлиять на производительность. Если не уверены, оставьте значение По умолчанию.</string>
|
||||||
<string name="gpu_fence_behavior">Поведение барьеров ГПУ</string>
|
|
||||||
<string name="gpu_fence_behavior_description">Управляет поведением синхронизации через барьеры ГПУ. Мгновенный — самый быстрый вариант, но может вызывать некоторые проблемы. Сбалансированный обеспечивает лучшую совместимость и может исправлять проблемы в некоторых играх. Точный ещё больше повышает совместимость ценой некоторого снижения производительности. Строгий — самый медленный вариант, но может исправлять проблемы, требующие более строгой синхронизации. По умолчанию соответствует настройке точности ГПУ.</string>
|
|
||||||
<string name="anisotropic_filtering">Анизотропная фильтрация</string>
|
<string name="anisotropic_filtering">Анизотропная фильтрация</string>
|
||||||
<string name="anisotropic_filtering_description">Улучшает качество текстур под углом</string>
|
<string name="anisotropic_filtering_description">Улучшает качество текстур под углом</string>
|
||||||
<string name="vram_usage_mode">Режим VRAM</string>
|
<string name="vram_usage_mode">Режим VRAM</string>
|
||||||
@@ -495,8 +490,6 @@
|
|||||||
<string name="renderer_reactive_flushing_description">Повышение точности рендеринга в некоторых играх за счет снижения производительности.</string>
|
<string name="renderer_reactive_flushing_description">Повышение точности рендеринга в некоторых играх за счет снижения производительности.</string>
|
||||||
<string name="enable_buffer_history">Включить историю буфера</string>
|
<string name="enable_buffer_history">Включить историю буфера</string>
|
||||||
<string name="enable_buffer_history_description">Позволяет обращаться к предыдущим состояниям буфера. Эта опция может повысить качество рендеринга и стабильность производительности в некоторых играх.</string>
|
<string name="enable_buffer_history_description">Позволяет обращаться к предыдущим состояниям буфера. Эта опция может повысить качество рендеринга и стабильность производительности в некоторых играх.</string>
|
||||||
<string name="enable_gpu_buffer_readback">Включить обратное чтение буфера ГПУ</string>
|
|
||||||
<string name="enable_gpu_buffer_readback_description">Сохраняет измененные ГПУ данные буфера путем чтения их обратно перед выгрузками. Некоторые игры требуют этого, чтобы рендерить определенные эффекты правильно. Может вызывать проблемы если оборудование не может обработать дополнительную рабочую нагрузку.</string>
|
|
||||||
<string name="use_optimized_vertex_buffers">Оптимизированные вершинные буферы</string>
|
<string name="use_optimized_vertex_buffers">Оптимизированные вершинные буферы</string>
|
||||||
<string name="use_optimized_vertex_buffers_description">Включает оптимизированную привязку вершинного буфера для повышения производительности. Требует Mesa Turnip 26.0+ / QCOM. Приводит к вылету на старых версиях драйверов Turnip (25.3 и ниже).</string>
|
<string name="use_optimized_vertex_buffers_description">Включает оптимизированную привязку вершинного буфера для повышения производительности. Требует Mesa Turnip 26.0+ / QCOM. Приводит к вылету на старых версиях драйверов Turnip (25.3 и ниже).</string>
|
||||||
|
|
||||||
@@ -571,12 +564,6 @@
|
|||||||
<string name="gpu_log_level_description">Уровень детализации логов ГПУ (больше значение = больше деталей, выше нагрузка)</string>
|
<string name="gpu_log_level_description">Уровень детализации логов ГПУ (больше значение = больше деталей, выше нагрузка)</string>
|
||||||
<string name="gpu_log_vulkan_calls">Записывать вызовы Vulkan API</string>
|
<string name="gpu_log_vulkan_calls">Записывать вызовы Vulkan API</string>
|
||||||
<string name="gpu_log_vulkan_calls_description">Отслеживать все вызовы Vulkan API в кольцевом буфере</string>
|
<string name="gpu_log_vulkan_calls_description">Отслеживать все вызовы Vulkan API в кольцевом буфере</string>
|
||||||
<string name="gpu_log_shader_dumps">Выгрузить SPIR-V шейдеры</string>
|
|
||||||
<string name="gpu_log_shader_dumps_description">Сохранять перекомпилированные SPIR-V бинарные файлы (.spv) в папку дампа. Проверять с помощью spirv-dis/spirv-cross/spirv-val.</string>
|
|
||||||
<string name="dump_guest_shaders">Выгрузить гостевые (Maxwell) шейдеры</string>
|
|
||||||
<string name="dump_guest_shaders_description">Сохранять файлы байткода гостевых шейдеров Maxwell (*.ash) в папку дампа. Проверять с помощью nvdisasm.</string>
|
|
||||||
<string name="dump_macros">Выгрузить макросы Maxwell</string>
|
|
||||||
<string name="dump_macros_description">Сохранять файлы макропрограмм Maxwell (*.macro) в папку дампа. Проверять с помощью envydis.</string>
|
|
||||||
<string name="gpu_log_memory_tracking">Отслеживать память ГПУ</string>
|
<string name="gpu_log_memory_tracking">Отслеживать память ГПУ</string>
|
||||||
<string name="gpu_log_memory_tracking_description">Мониторить выделение и освобождение памяти ГПУ</string>
|
<string name="gpu_log_memory_tracking_description">Мониторить выделение и освобождение памяти ГПУ</string>
|
||||||
<string name="gpu_log_driver_debug">Отладочная информация драйвера</string>
|
<string name="gpu_log_driver_debug">Отладочная информация драйвера</string>
|
||||||
@@ -1003,13 +990,6 @@
|
|||||||
<string name="dma_accuracy_unsafe">Небезопасно</string>
|
<string name="dma_accuracy_unsafe">Небезопасно</string>
|
||||||
<string name="dma_accuracy_safe">Безопасный</string>
|
<string name="dma_accuracy_safe">Безопасный</string>
|
||||||
|
|
||||||
<!-- GPU Fence Behavior -->
|
|
||||||
<string name="gpu_fence_behavior_default">По умолчанию</string>
|
|
||||||
<string name="gpu_fence_behavior_immediate">Мгновенный</string>
|
|
||||||
<string name="gpu_fence_behavior_balanced">Сбалансированный</string>
|
|
||||||
<string name="gpu_fence_behavior_accurate">Точный</string>
|
|
||||||
<string name="gpu_fence_behavior_strict">Строгий</string>
|
|
||||||
|
|
||||||
<string name="vram_usage_conservative">Консервативный</string>
|
<string name="vram_usage_conservative">Консервативный</string>
|
||||||
<string name="vram_usage_aggressive">Агрессивный</string>
|
<string name="vram_usage_aggressive">Агрессивный</string>
|
||||||
|
|
||||||
|
|||||||
@@ -469,6 +469,7 @@
|
|||||||
<string name="advanced">Додаткові</string>
|
<string name="advanced">Додаткові</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">Режим ГП</string>
|
<string name="renderer_accuracy">Режим ГП</string>
|
||||||
|
<string name="renderer_accuracy_description">Керує режимом емуляції ГП. Більшість ігор добре візуалізуються з режимами «Швидко» або «Збалансовано», але деякі ігри можуть потребувати режиму «Точно». Частинки зазвичай правильно візуалізуються лише з режимом «Точно».</string>
|
||||||
<string name="dma_accuracy">Точність DMA</string>
|
<string name="dma_accuracy">Точність DMA</string>
|
||||||
<string name="dma_accuracy_description">Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням.</string>
|
<string name="dma_accuracy_description">Керує точністю DMA. Безпечна точність може виправити проблеми в деяких іграх, але в деяких випадках також може вплинути на продуктивність. Якщо не впевнені, залиште це значення за замовчуванням.</string>
|
||||||
<string name="anisotropic_filtering">Анізотропне фільтрування</string>
|
<string name="anisotropic_filtering">Анізотропне фільтрування</string>
|
||||||
|
|||||||
@@ -463,7 +463,7 @@
|
|||||||
<string name="advanced">高级</string>
|
<string name="advanced">高级</string>
|
||||||
|
|
||||||
<string name="renderer_accuracy">GPU 模式</string>
|
<string name="renderer_accuracy">GPU 模式</string>
|
||||||
<string name="renderer_accuracy_description">控制 GPU 模拟模式。大多数游戏在“快速”模式下渲染效果良好,但有些游戏仍需使用“精确”模式。而粒子效果通常只有在“精确”模式下才能正确渲染。</string>
|
<string name="renderer_accuracy_description">控制 GPU 模拟模式。大多数游戏在“快速”或“均衡”模式下都能获得良好的渲染,但有些游戏仍需使用“精确”模式。粒子效果通常只有在“精确”模式下才能正确渲染。</string>
|
||||||
<string name="dma_accuracy">DMA 精度</string>
|
<string name="dma_accuracy">DMA 精度</string>
|
||||||
<string name="dma_accuracy_description">控制 DMA 的精准度。安全精度可以修复存在于某些游戏中的问题,但在某些情况下也会对性能造成影响。如不确定,请保持“默认”。</string>
|
<string name="dma_accuracy_description">控制 DMA 的精准度。安全精度可以修复存在于某些游戏中的问题,但在某些情况下也会对性能造成影响。如不确定,请保持“默认”。</string>
|
||||||
<string name="gpu_fence_behavior">GPU 围栏行为</string>
|
<string name="gpu_fence_behavior">GPU 围栏行为</string>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
<string name="app_disclaimer">本軟體可執行Nintendo Switch主機的遊戲,軟體不提供遊戲和金鑰檔案。<br/> <br/>在開始之前,請先安裝您的 <<![CDATA[ <b>prod.keys</b> ]]> 檔案,<br /><br /><![CDATA[<a href=\"https://yuzu-mirror.github.io/help/quickstart\">了解更多</a>]]></string>
|
<string name="app_disclaimer">本軟體可執行Nintendo Switch主機的遊戲,軟體不提供遊戲和金鑰檔案。<br/> <br/>在開始之前,請先安裝您的 <<![CDATA[ <b>prod.keys</b> ]]> 檔案,<br /><br /><![CDATA[<a href=\"https://yuzu-mirror.github.io/help/quickstart\">了解更多</a>]]></string>
|
||||||
<string name="notice_notification_channel_name">通知和錯誤</string>
|
<string name="notice_notification_channel_name">通知和錯誤</string>
|
||||||
<string name="notice_notification_channel_description">發生錯誤時顯示通知</string>
|
<string name="notice_notification_channel_description">發生錯誤時顯示通知。</string>
|
||||||
<string name="notification_permission_not_granted">未授予通知權限!</string>
|
<string name="notification_permission_not_granted">未授予通知權限!</string>
|
||||||
<string name="app_notification_channel_description">Eden模擬器通知</string>
|
<string name="app_notification_channel_description">Eden模擬器通知</string>
|
||||||
<string name="app_notification_running">Eden正在執行</string>
|
<string name="app_notification_running">Eden正在執行</string>
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
<string name="value_too_high">範圍最大必須為%1$d</string>
|
<string name="value_too_high">範圍最大必須為%1$d</string>
|
||||||
<string name="invalid_value">無效的範圍</string>
|
<string name="invalid_value">無效的範圍</string>
|
||||||
|
|
||||||
<string name="using_per_game_config">使用個別設定中</string>
|
<string name="using_per_game_config">使用自定義組態中</string>
|
||||||
|
|
||||||
<!-- Input Overlay -->
|
<!-- Input Overlay -->
|
||||||
<string name="show_input_overlay">顯示虛擬按鍵</string>
|
<string name="show_input_overlay">顯示虛擬按鍵</string>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
<string name="overlay_snap_to_grid_description">編輯時將虛擬按鍵與網格對齊</string>
|
<string name="overlay_snap_to_grid_description">編輯時將虛擬按鍵與網格對齊</string>
|
||||||
<string name="overlay_grid_size">網格大小</string>
|
<string name="overlay_grid_size">網格大小</string>
|
||||||
<string name="overlay_grid_size_description">調整網格格線間距</string>
|
<string name="overlay_grid_size_description">調整網格格線間距</string>
|
||||||
<string name="input_overlay_behavior">隱藏</string>
|
<string name="input_overlay_behavior">行為模式</string>
|
||||||
<string name="overlay_auto_hide">自動隱藏虛擬按鍵</string>
|
<string name="overlay_auto_hide">自動隱藏虛擬按鍵</string>
|
||||||
<string name="overlay_auto_hide_description">在未使用虛擬按鍵幾秒後自動隱藏</string>
|
<string name="overlay_auto_hide_description">在未使用虛擬按鍵幾秒後自動隱藏</string>
|
||||||
<string name="enable_input_overlay_auto_hide">啟用自動隱藏虛擬按鍵</string>
|
<string name="enable_input_overlay_auto_hide">啟用自動隱藏虛擬按鍵</string>
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<string name="shaders_suffix">著色器</string>
|
<string name="shaders_suffix">著色器</string>
|
||||||
<string name="charging">(充電中)</string>
|
<string name="charging">(充電中)</string>
|
||||||
|
|
||||||
<string name="system_info_label">系統:</string>
|
<string name="system_info_label">系統:</string>
|
||||||
<string name="show_stats_overlay">顯示效能統計疊加層</string>
|
<string name="show_stats_overlay">顯示效能統計疊加層</string>
|
||||||
<string name="stats_overlay_customization">自訂</string>
|
<string name="stats_overlay_customization">自訂</string>
|
||||||
<string name="stats_overlay_items">可見項目</string>
|
<string name="stats_overlay_items">可見項目</string>
|
||||||
@@ -54,20 +54,18 @@
|
|||||||
<string name="enable_stats_overlay_">啟用效能統計疊加層</string>
|
<string name="enable_stats_overlay_">啟用效能統計疊加層</string>
|
||||||
<string name="stats_overlay_options_description">設定疊加層中顯示的資訊</string>
|
<string name="stats_overlay_options_description">設定疊加層中顯示的資訊</string>
|
||||||
<string name="show_fps">顯示FPS</string>
|
<string name="show_fps">顯示FPS</string>
|
||||||
<string name="show_fps_description">顯示當前影格率</string>
|
<string name="show_fps_description">顯示當前幀率</string>
|
||||||
<string name="show_frametime">顯示影格時間</string>
|
<string name="show_frametime">顯示幀時間</string>
|
||||||
<string name="show_app_ram_usage">顯示應用程式的記憶體用量</string>
|
<string name="show_app_ram_usage">顯示應用程式的記憶體用量</string>
|
||||||
<string name="show_app_ram_usage_description">顯示模擬器的記憶體用量</string>
|
<string name="show_app_ram_usage_description">顯示模擬器正在使用的記憶體量</string>
|
||||||
<string name="show_system_ram_usage">顯示系統記憶體用量</string>
|
<string name="show_system_ram_usage">顯示系統記憶體用量</string>
|
||||||
<string name="show_system_ram_usage_description">顯示系統的記憶體用量</string>
|
<string name="show_system_ram_usage_description">顯示系統使用的記憶體量</string>
|
||||||
<string name="show_bat_temperature">顯示電池溫度</string>
|
<string name="show_bat_temperature">顯示電池溫度</string>
|
||||||
<string name="bat_temperature_unit">電池溫度單位</string>
|
<string name="bat_temperature_unit">電池溫度單位</string>
|
||||||
<string name="show_power_info">顯示電池資訊</string>
|
<string name="show_power_info">顯示電池資訊</string>
|
||||||
<string name="show_power_info_description">顯示當前功耗和電池可續航時間</string>
|
<string name="show_power_info_description">顯示當前功耗和電池可續航時間</string>
|
||||||
<string name="show_shaders_building">當著色器在編譯時顯示</string>
|
<string name="show_shaders_building">當著色器在編譯時顯示</string>
|
||||||
<string name="show_shaders_building_description">顯示正在編譯的著色器數量</string>
|
<string name="show_shaders_building_description">顯示正在編譯的著色器數量</string>
|
||||||
<string name="pipeline_worker_cores">管線工作執行緒</string>
|
|
||||||
<string name="pipeline_worker_cores_description">設定用於建置 Vulkan 管線的 CPU 核心數量,設定的數值越大效能越好,但溫度也會上升更快</string>
|
|
||||||
<string name="overlay_position">疊加層位置</string>
|
<string name="overlay_position">疊加層位置</string>
|
||||||
<string name="overlay_position_description">選擇疊加層在畫面上的顯示位置</string>
|
<string name="overlay_position_description">選擇疊加層在畫面上的顯示位置</string>
|
||||||
<string name="overlay_position_top_left">左上</string>
|
<string name="overlay_position_top_left">左上</string>
|
||||||
@@ -80,10 +78,10 @@
|
|||||||
<string name="perf_overlay_background_description">為疊加層添加背景以提高可讀性</string>
|
<string name="perf_overlay_background_description">為疊加層添加背景以提高可讀性</string>
|
||||||
|
|
||||||
<!-- Device Overlay settings -->
|
<!-- Device Overlay settings -->
|
||||||
<string name="show_soc_overlay">顯示裝置資訊疊加層</string>
|
<string name="show_soc_overlay">顯示裝置資訊浮層</string>
|
||||||
<string name="enable_soc_overlay">啟用裝置疊加層</string>
|
<string name="enable_soc_overlay">啟用裝置浮層</string>
|
||||||
<string name="soc_overlay_options">裝置疊加層</string>
|
<string name="soc_overlay_options">裝置浮層</string>
|
||||||
<string name="soc_overlay_options_description">設定裝置疊加層中顯示的資訊</string>
|
<string name="soc_overlay_options_description">設定裝置浮層中顯示的資訊</string>
|
||||||
|
|
||||||
<string name="show_build_id">顯示Eden的組建版本</string>
|
<string name="show_build_id">顯示Eden的組建版本</string>
|
||||||
<string name="show_driver_version">顯示圖形驅動程式的版本</string>
|
<string name="show_driver_version">顯示圖形驅動程式的版本</string>
|
||||||
@@ -94,10 +92,10 @@
|
|||||||
|
|
||||||
<!-- Eden\'s Veil -->
|
<!-- Eden\'s Veil -->
|
||||||
<string name="buffer_reorder_disable">停用緩衝區重新排序</string>
|
<string name="buffer_reorder_disable">停用緩衝區重新排序</string>
|
||||||
<string name="buffer_reorder_disable_description">勾選時,停用映射記憶體上傳的重新排序功能,允許將上傳與特定繪製關聯。某些情況下可能會降低效能</string>
|
<string name="buffer_reorder_disable_description">勾選時,停用映射記憶體上傳的重新排序功能,允許將上傳與特定繪製關聯。某些情況下可能會降低效能。</string>
|
||||||
|
|
||||||
<string name="use_sync_core">同步核心速度</string>
|
<string name="use_sync_core">同步核心速度</string>
|
||||||
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能</string>
|
<string name="use_sync_core_description">將核心速度與最大速度百分比同步,在不改變遊戲實際速度的情況下提高效能。</string>
|
||||||
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
|
<string name="cpuopt_unsafe_host_mmu">啟用主機 MMU 模擬</string>
|
||||||
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
|
<string name="cpuopt_unsafe_host_mmu_description">此最佳化可加速來賓程式的記憶體存取。啟用後,來賓記憶體讀取/寫入將直接在記憶體中執行並利用主機的 MMU。停用此功能將強制所有記憶體存取使用軟體 MMU 模擬。</string>
|
||||||
<string name="debug_knobs">偵錯開關</string>
|
<string name="debug_knobs">偵錯開關</string>
|
||||||
@@ -173,7 +171,7 @@
|
|||||||
<string name="multiplayer_ban">封鎖使用者</string>
|
<string name="multiplayer_ban">封鎖使用者</string>
|
||||||
<string name="multiplayer_room_browser">公開房間</string>
|
<string name="multiplayer_room_browser">公開房間</string>
|
||||||
<string name="multiplayer_no_rooms_found">未找到公開房間</string>
|
<string name="multiplayer_no_rooms_found">未找到公開房間</string>
|
||||||
<string name="multiplayer_password_required">需要輸入密碼</string>
|
<string name="multiplayer_password_required">需輸入密碼</string>
|
||||||
<string name="multiplayer_player_count">:%1$d/%2$d</string>
|
<string name="multiplayer_player_count">:%1$d/%2$d</string>
|
||||||
<string name="multiplayer_game">遊戲</string>
|
<string name="multiplayer_game">遊戲</string>
|
||||||
<string name="multiplayer_no_game_info">任意遊戲</string>
|
<string name="multiplayer_no_game_info">任意遊戲</string>
|
||||||
@@ -192,7 +190,7 @@
|
|||||||
<string name="multiplayer_nickname_invalid">使用者名稱無效,請在系統→網路中檢查設定</string>
|
<string name="multiplayer_nickname_invalid">使用者名稱無效,請在系統→網路中檢查設定</string>
|
||||||
<string name="multiplayer_token_error">必須為48個字元,且僅包含小寫字母a-z</string>
|
<string name="multiplayer_token_error">必須為48個字元,且僅包含小寫字母a-z</string>
|
||||||
<string name="multiplayer_port_error">埠號需為1-65535</string>
|
<string name="multiplayer_port_error">埠號需為1-65535</string>
|
||||||
<string name="cancel">略過</string>
|
<string name="cancel">取消</string>
|
||||||
<string name="ok">確定</string>
|
<string name="ok">確定</string>
|
||||||
<string name="refresh">重新整理</string>
|
<string name="refresh">重新整理</string>
|
||||||
<string name="room_list">房間列表</string>
|
<string name="room_list">房間列表</string>
|
||||||
@@ -246,21 +244,21 @@
|
|||||||
<string name="home_search_games">搜尋遊戲</string>
|
<string name="home_search_games">搜尋遊戲</string>
|
||||||
<string name="search_settings">搜尋設定</string>
|
<string name="search_settings">搜尋設定</string>
|
||||||
<string name="install_prod_keys">安裝 prod.keys</string>
|
<string name="install_prod_keys">安裝 prod.keys</string>
|
||||||
<string name="install_prod_keys_description">需要用來解密零售遊戲</string>
|
<string name="install_prod_keys_description">需要解密零售遊戲</string>
|
||||||
<string name="install_prod_keys_warning">跳過安裝金鑰?</string>
|
<string name="install_prod_keys_warning">跳過安裝金鑰?</string>
|
||||||
<string name="install_prod_keys_warning_description">模擬零售遊戲需要有效的金鑰,如果不安裝將僅有自製遊戲可以運作</string>
|
<string name="install_prod_keys_warning_description">模擬零售遊戲需要有效的金鑰,若要繼續,將僅有自製遊戲可以運作。</string>
|
||||||
<string name="install_prod_keys_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
<string name="install_prod_keys_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
||||||
<string name="install_firmware_warning">跳過安裝韌體?</string>
|
<string name="install_firmware_warning">跳過安裝韌體?</string>
|
||||||
<string name="emulator_data">設定模擬器資料</string>
|
<string name="emulator_data">設定模擬器資料</string>
|
||||||
<string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動QLaunch小程式</string>
|
<string name="emulator_data_description">模擬器需要金鑰才能正常執行,同時建議安裝韌體以啟動QLaunch小程式</string>
|
||||||
<string name="permissions">授予權限</string>
|
<string name="permissions">授予權限</string>
|
||||||
<string name="permissions_description">授予權限以使用模擬器的特定功能</string>
|
<string name="permissions_description">授予權限以使用模擬器的特定功能</string>
|
||||||
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作</string>
|
<string name="install_firmware_warning_description">許多遊戲需要韌體才能正常運作。</string>
|
||||||
<string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
<string name="install_firmware_warning_help">https://yuzu-mirror.github.io/help/quickstart/#guide-introduction</string>
|
||||||
<string name="notifications">通知</string>
|
<string name="notifications">通知</string>
|
||||||
<string name="notifications_description">使用下方的按鈕授予通知權限</string>
|
<string name="notifications_description">使用下方的按鈕授予通知權限。</string>
|
||||||
<string name="permission_denied">權限遭拒</string>
|
<string name="permission_denied">權限遭拒</string>
|
||||||
<string name="permission_denied_description">您多次拒絕了要求的權限,現在您需要在系統設定中手動授予</string>
|
<string name="permission_denied_description">您曾多次拒絕了權限要求,現在您需要在系統設定中手動授予權限。</string>
|
||||||
<string name="about">關於</string>
|
<string name="about">關於</string>
|
||||||
<string name="about_description">組建版本、製作群、以及更多</string>
|
<string name="about_description">組建版本、製作群、以及更多</string>
|
||||||
<string name="system_information">裝置資訊</string>
|
<string name="system_information">裝置資訊</string>
|
||||||
@@ -287,7 +285,7 @@
|
|||||||
<string name="warning_skip">跳過</string>
|
<string name="warning_skip">跳過</string>
|
||||||
<string name="warning_cancel">取消</string>
|
<string name="warning_cancel">取消</string>
|
||||||
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
|
<string name="install_amiibo_keys">安裝 Amiibo 金鑰</string>
|
||||||
<string name="install_amiibo_keys_description">若要在遊戲中使用 Amiibo 得先安裝</string>
|
<string name="install_amiibo_keys_description">需要在遊戲中使用 Amiibo</string>
|
||||||
<string name="gpu_driver_fetcher">GPU驅動程式下載器</string>
|
<string name="gpu_driver_fetcher">GPU驅動程式下載器</string>
|
||||||
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
|
<string name="gpu_driver_manager">GPU 驅動程式管理員</string>
|
||||||
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
|
<string name="install_gpu_driver_description">安裝替代驅動程式以取得潛在的更佳效能或準確度</string>
|
||||||
@@ -302,14 +300,14 @@
|
|||||||
<string name="notification_no_directory_link">無法開啟 Eden 目錄</string>
|
<string name="notification_no_directory_link">無法開啟 Eden 目錄</string>
|
||||||
<string name="notification_no_directory_link_description">請使用檔案管理員的側邊面板手動定位到使用者資料夾。</string>
|
<string name="notification_no_directory_link_description">請使用檔案管理員的側邊面板手動定位到使用者資料夾。</string>
|
||||||
<string name="manage_save_data">管理儲存資料</string>
|
<string name="manage_save_data">管理儲存資料</string>
|
||||||
<string name="manage_save_data_description">導入/導出遊戲的儲存資料</string>
|
<string name="manage_save_data_description">已找到儲存資料,請選取下方的選項。</string>
|
||||||
<string name="import_save_warning">導入儲存資料</string>
|
<string name="import_save_warning">導入儲存資料</string>
|
||||||
<string name="import_save_warning_description">這將會以提供的檔案覆寫現有的該遊戲儲存資料,您確定要繼續嗎?</string>
|
<string name="import_save_warning_description">這將會以提供的檔案覆寫所有現有的儲存資料,您確定要繼續嗎?</string>
|
||||||
<string name="save_files_importing">正在導入儲存資料…</string>
|
<string name="save_files_importing">正在導入儲存資料…</string>
|
||||||
<string name="save_files_exporting">正在導出儲存資料…</string>
|
<string name="save_files_exporting">正在導出儲存資料…</string>
|
||||||
<string name="save_file_imported_success">已成功導入</string>
|
<string name="save_file_imported_success">已成功導入</string>
|
||||||
<string name="save_file_invalid_zip_structure">無效的儲存目錄結構</string>
|
<string name="save_file_invalid_zip_structure">無效的儲存目錄結構</string>
|
||||||
<string name="save_file_invalid_zip_structure_description">首個子資料夾名稱必須為遊戲 ID</string>
|
<string name="save_file_invalid_zip_structure_description">首個子資料夾名稱必須為遊戲標題 ID。</string>
|
||||||
<string name="install_firmware">安裝韌體</string>
|
<string name="install_firmware">安裝韌體</string>
|
||||||
<string name="install_firmware_description">韌體必須為 ZIP 壓縮檔,將會用於部分遊戲的啟動</string>
|
<string name="install_firmware_description">韌體必須為 ZIP 壓縮檔,將會用於部分遊戲的啟動</string>
|
||||||
<string name="firmware_installing">正在安裝韌體</string>
|
<string name="firmware_installing">正在安裝韌體</string>
|
||||||
@@ -319,15 +317,12 @@
|
|||||||
<string name="share_log">分享偵錯記錄</string>
|
<string name="share_log">分享偵錯記錄</string>
|
||||||
<string name="share_log_description">分享 Eden 的記錄檔以便對相關問題進行偵錯</string>
|
<string name="share_log_description">分享 Eden 的記錄檔以便對相關問題進行偵錯</string>
|
||||||
<string name="share_log_missing">找不到日誌檔案</string>
|
<string name="share_log_missing">找不到日誌檔案</string>
|
||||||
<string name="share_gpu_log">分享 GPU 日誌</string>
|
|
||||||
<string name="share_gpu_log_description">分享 Eden 的 GPU 日誌以對圖形問題進行偵錯</string>
|
|
||||||
<string name="share_gpu_log_missing">找不到 GPU 日誌檔案</string>
|
|
||||||
<string name="install_game_content">安裝遊戲內容</string>
|
<string name="install_game_content">安裝遊戲內容</string>
|
||||||
<string name="install_game_content_description">安裝遊戲更新或 DLC</string>
|
<string name="install_game_content_description">安裝遊戲更新或 DLC</string>
|
||||||
<string name="installing_game_content">正在安裝內容…</string>
|
<string name="installing_game_content">正在安裝內容…</string>
|
||||||
<string name="install_game_content_failure">安裝檔案至 NAND 時發生錯誤</string>
|
<string name="install_game_content_failure">安裝檔案至 NAND 時發生錯誤</string>
|
||||||
<string name="install_game_content_failure_description">請確保內容有效並且 prod.keys 檔案已安裝</string>
|
<string name="install_game_content_failure_description">請確保內容有效並且 prod.keys 檔案已安裝。</string>
|
||||||
<string name="install_game_content_failure_base">為避免產生衝突,無法直接安裝遊戲本體</string>
|
<string name="install_game_content_failure_base">為避免可能的衝突,無法直接安裝遊戲本體。</string>
|
||||||
<string name="install_game_content_failed_count">%1$d 安裝錯誤</string>
|
<string name="install_game_content_failed_count">%1$d 安裝錯誤</string>
|
||||||
<string name="install_game_content_success">遊戲內容已成功安裝</string>
|
<string name="install_game_content_success">遊戲內容已成功安裝</string>
|
||||||
<string name="install_game_content_success_install">%1$d 安裝成功</string>
|
<string name="install_game_content_success_install">%1$d 安裝成功</string>
|
||||||
@@ -336,12 +331,12 @@
|
|||||||
<string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string>
|
<string name="custom_driver_not_supported">您的裝置不支援自訂驅動程式</string>
|
||||||
<string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式。\n請以後再來查看是否已新增支援!</string>
|
<string name="custom_driver_not_supported_description">此裝置不支援注入自訂驅動程式。\n請以後再來查看是否已新增支援!</string>
|
||||||
<string name="manage_yuzu_data">管理 Eden 資料</string>
|
<string name="manage_yuzu_data">管理 Eden 資料</string>
|
||||||
<string name="manage_yuzu_data_description">安裝韌體、金鑰,導入/導出使用者資料及安裝其它項目!</string>
|
<string name="manage_yuzu_data_description">安裝韌體、金鑰,導入/導出使用者資料及安裝其他項目!</string>
|
||||||
<string name="game_folders">遊戲資料夾</string>
|
<string name="game_folders">遊戲資料夾</string>
|
||||||
<string name="deep_scan">深度掃描</string>
|
<string name="deep_scan">深度掃描</string>
|
||||||
<string name="add_game_folder">新增遊戲資料夾</string>
|
<string name="add_game_folder">新增遊戲資料夾</string>
|
||||||
<string name="folder_already_added">這個資料夾已經新增過了!</string>
|
<string name="folder_already_added">這個資料夾已經新增過了!</string>
|
||||||
<string name="game_folder_properties">遊戲資料夾設定</string>
|
<string name="game_folder_properties">遊戲資料夾屬性</string>
|
||||||
<plurals name="saves_import_failed">
|
<plurals name="saves_import_failed">
|
||||||
<item quantity="other">%d 個存檔導入失敗</item>
|
<item quantity="other">%d 個存檔導入失敗</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
@@ -352,30 +347,28 @@
|
|||||||
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
|
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
|
||||||
<string name="verify_installed_content_description">檢查所有已安裝的內容是否有損壞</string>
|
<string name="verify_installed_content_description">檢查所有已安裝的內容是否有損壞</string>
|
||||||
|
|
||||||
<string name="keys_missing">缺少 prod.keys</string>
|
<string name="keys_missing">缺少解密金鑰</string>
|
||||||
<string name="keys_missing_description">無法解密韌體和零售遊戲</string>
|
<string name="keys_missing_description">無法解密韌體和零售遊戲</string>
|
||||||
<string name="keys_missing_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
|
<string name="keys_missing_help">https://yuzu-mirror.github.io/help/quickstart/#dumping-decryption-keys</string>
|
||||||
|
|
||||||
<string name="uninstall_firmware">解除安裝韌體</string>
|
<string name="uninstall_firmware">解除安裝韌體</string>
|
||||||
<string name="uninstall_firmware_description">解除安裝韌體將從裝置中刪除它並可能影響遊戲相容性</string>
|
<string name="uninstall_firmware_description">解除安裝韌體將從裝置中刪除它並可能影響遊戲相容性。</string>
|
||||||
<string name="firmware_uninstalling">正在解除安裝韌體...</string>
|
<string name="firmware_uninstalling">正在解除安裝韌體...</string>
|
||||||
<string name="firmware_uninstalled_success">韌體解除安裝成功</string>
|
<string name="firmware_uninstalled_success">韌體解除安裝成功</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="keys_failed">金鑰安裝失敗</string>
|
<string name="keys_failed">金鑰安裝失敗</string>
|
||||||
<string name="keys_install_success">金鑰安裝成功</string>
|
<string name="keys_install_success">金鑰安裝成功</string>
|
||||||
<string name="error_keys_copy_failed">一個或多個金鑰安裝失敗</string>
|
<string name="error_keys_copy_failed">一個或多個金鑰複製失敗。</string>
|
||||||
<string name="error_keys_invalid_filename">請確保金鑰檔案具有.keys副檔名後重試。</string>
|
<string name="error_keys_invalid_filename">請確保金鑰檔案具有.keys副檔名後重試。</string>
|
||||||
<string name="error_keys_failed_init">金鑰初始化失敗。請檢查您的轉儲工具是否為最新版本並重新轉儲金鑰。</string>
|
<string name="error_keys_failed_init">金鑰初始化失敗。請檢查您的轉儲工具是否為最新版本並重新轉儲金鑰。</string>
|
||||||
|
|
||||||
<!-- Applet launcher strings -->
|
<!-- Applet launcher strings -->
|
||||||
<string name="qlaunch_applet">Qlaunch</string>
|
<string name="qlaunch_applet">Qlaunch</string>
|
||||||
<string name="qlaunch_description">從Switch系統主畫面啟動應用程式(目前僅支援英文)</string>
|
<string name="qlaunch_description">從系統主畫面啟動應用程式</string>
|
||||||
<string name="applets">小程式啟動器</string>
|
<string name="applets">小程式啟動器</string>
|
||||||
<string name="applets_description">使用已安裝的韌體啟動系統小程式</string>
|
<string name="applets_description">使用已安裝的韌體啟動系統小程式</string>
|
||||||
<string name="applets_error_firmware">未安裝韌體</string>
|
|
||||||
<string name="applets_error_applet">無法使用小程式</string>
|
<string name="applets_error_applet">無法使用小程式</string>
|
||||||
<string name="applets_error_description"><![CDATA[請確定您的<a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a>檔案和<a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">韌體</a>已安裝並重試]]></string>
|
|
||||||
<string name="album_applet">相簿</string>
|
<string name="album_applet">相簿</string>
|
||||||
<string name="album_applet_description">使用系統相片檢視器查看儲存在使用者螢幕截圖資料夾中的影像</string>
|
<string name="album_applet_description">使用系統相片檢視器查看儲存在使用者螢幕截圖資料夾中的影像</string>
|
||||||
<string name="mii_edit_applet">Mii 編輯</string>
|
<string name="mii_edit_applet">Mii 編輯</string>
|
||||||
@@ -384,58 +377,47 @@
|
|||||||
<string name="cabinet_applet_description">編輯、刪除儲存在 amiibo 上的資料</string>
|
<string name="cabinet_applet_description">編輯、刪除儲存在 amiibo 上的資料</string>
|
||||||
<string name="cabinet_launcher">Cabinet 啟動器</string>
|
<string name="cabinet_launcher">Cabinet 啟動器</string>
|
||||||
<string name="cabinet_nickname_and_owner">暱稱和擁有者設定</string>
|
<string name="cabinet_nickname_and_owner">暱稱和擁有者設定</string>
|
||||||
<string name="cabinet_game_data_eraser">刪除遊戲資料</string>
|
<string name="cabinet_game_data_eraser">遊戲資料橡皮擦</string>
|
||||||
<string name="cabinet_restorer">還原程式</string>
|
<string name="cabinet_restorer">還原程式</string>
|
||||||
<string name="cabinet_formatter">格式化程式</string>
|
<string name="cabinet_formatter">格式化程式</string>
|
||||||
|
|
||||||
<!-- About screen strings -->
|
<!-- About screen strings -->
|
||||||
<string name="gaia_is_not_real">Gaia 不存在</string>
|
<string name="gaia_is_not_real">Gaia不是真的</string>
|
||||||
<string name="copied_to_clipboard">已複製到剪貼簿</string>
|
<string name="copied_to_clipboard">已複製到剪貼簿</string>
|
||||||
<string name="about_app_description">一個開放原始碼的 Switch 模擬器</string>
|
<string name="about_app_description">一個開放原始碼的 Switch 模擬器</string>
|
||||||
<string name="contributors">參與者</string>
|
<string name="contributors">參與者</string>
|
||||||
<string name="contributors_description">這些人讓 Eden Android 版成為可能</string>
|
|
||||||
<string name="licenses_description">這些專案使 Eden Android 版成為可能</string>
|
<string name="licenses_description">這些專案使 Eden Android 版成為可能</string>
|
||||||
<string name="build">組建版本</string>
|
<string name="build">組建版本</string>
|
||||||
<string name="user_data">使用者資料</string>
|
<string name="user_data">使用者資料</string>
|
||||||
<string name="user_data_description">導入/導出所有應用程式資料。\n\n導入使用者資料時,現有的使用者資料將被取代!\n\n直接從 Citron 導入使用者資料可能會出現問題,建議手動導入所有所需資料。</string>
|
<string name="user_data_description">導入/導出所有應用程式資料。\n\n導入使用者資料時,現有的使用者資料將被取代!\n\n直接從 Citron 導入資料可能會出現問題,建議手動導入所有所需資料。</string>
|
||||||
<string name="exporting_user_data">正在導出使用者資料…</string>
|
<string name="exporting_user_data">正在導出使用者資料…</string>
|
||||||
<string name="importing_user_data">正在導入使用者資料…</string>
|
<string name="importing_user_data">正在導入使用者資料…</string>
|
||||||
<string name="invalid_yuzu_backup">無效的 Eden 備份</string>
|
<string name="invalid_yuzu_backup">無效的 Eden 備份</string>
|
||||||
<string name="user_data_export_success">使用者資料導出成功</string>
|
<string name="user_data_export_success">使用者資料導出成功</string>
|
||||||
<string name="user_data_import_success">使用者資料導入成功</string>
|
<string name="user_data_import_success">使用者資料導入成功</string>
|
||||||
<string name="user_data_export_cancelled">導出已取消</string>
|
<string name="user_data_export_cancelled">導出已取消</string>
|
||||||
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次</string>
|
<string name="user_data_import_failed_description">請確保使用者資料夾位於 zip 壓縮檔的根目錄,並在 config/config.ini 路徑中包含組態檔案,並再試一次。</string>
|
||||||
<!-- General settings strings -->
|
<!-- General settings strings -->
|
||||||
<string name="frame_limit_enable">限制模擬速度</string>
|
<string name="frame_limit_enable">限制速度</string>
|
||||||
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比</string>
|
<string name="frame_limit_enable_description">將模擬速度限制在標準速度的指定百分比。</string>
|
||||||
<string name="frame_limit_slider">限制速度百分比</string>
|
<string name="frame_limit_slider">限制速度百分比</string>
|
||||||
<string name="frame_limit_slider_description">指定模擬速度的百分比。100% 為標準速度,更高或更低的值將會減少或增加速度限制</string>
|
<string name="frame_limit_slider_description">指定限制模擬速度的百分比。100% 為標準速度,更高或更低的值將會增加或減少速度限制。</string>
|
||||||
<string name="turbo_speed_limit">加速模式</string>
|
|
||||||
<string name="turbo_speed_limit_description">當開啟加速模式時,模擬器將以此速度執行</string>
|
|
||||||
<string name="slow_speed_limit">慢速模式</string>
|
|
||||||
<string name="slow_speed_limit_description">當慢速模式開啟時,模擬器將會以此速度執行</string>
|
|
||||||
<string name="cpu_backend">CPU 後端</string>
|
<string name="cpu_backend">CPU 後端</string>
|
||||||
<string name="cpu_accuracy">CPU 準確度</string>
|
<string name="cpu_accuracy">CPU 準確度</string>
|
||||||
<string name="value_with_units">%1$s%2$s</string>
|
<string name="value_with_units">%1$s%2$s</string>
|
||||||
|
|
||||||
<string name="program_args">Homebrew 參數</string>
|
|
||||||
<string name="program_args_description">在啟動時傳遞給 Homebrew 的命令列參數(例如:-noglsl)</string>
|
|
||||||
|
|
||||||
<!-- System settings strings -->
|
<!-- System settings strings -->
|
||||||
<string name="device_name">裝置名稱</string>
|
<string name="device_name">裝置名稱</string>
|
||||||
<string name="use_docked_mode">底座模式</string>
|
<string name="use_docked_mode">底座模式</string>
|
||||||
<string name="use_docked_mode_description">提高解析度,降低效能。停用後將會使用手提模式,會降低解析度並提高效能</string>
|
<string name="use_docked_mode_description">提高解析度,降低效能。停用後將會使用手提模式,會降低解析度並提高效能。</string>
|
||||||
<string name="emulated_region">模擬區域</string>
|
<string name="emulated_region">模擬區域</string>
|
||||||
<string name="emulated_language">模擬語言</string>
|
<string name="emulated_language">模擬語言</string>
|
||||||
<string name="select_rtc_date">選擇 RTC 日期</string>
|
<string name="select_rtc_date">選擇 RTC 日期</string>
|
||||||
<string name="select_rtc_time">選擇 RTC 時間</string>
|
<string name="select_rtc_time">選擇 RTC 時間</string>
|
||||||
<string name="use_custom_rtc">自訂 RTC</string>
|
<string name="use_custom_rtc">自訂 RTC</string>
|
||||||
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間</string>
|
<string name="use_custom_rtc_description">允許您設定與您的目前系統時間相互獨立的自訂時間。</string>
|
||||||
<string name="set_custom_rtc">設定自訂 RTC</string>
|
<string name="set_custom_rtc">設定自訂 RTC</string>
|
||||||
|
|
||||||
<!-- CPU -->
|
|
||||||
<string name="fast_cpu_time">CPU 超頻</string>
|
|
||||||
<string name="fast_cpu_time_description">強制模擬 CPU 以更高的時脈運作,減少某些 FPS 限制。使用 加速 (1700MHz) 以 Switch 的最高原生時脈執行,或 高速 (2000MHz) 以雙倍時脈執行</string>
|
|
||||||
<string name="custom_cpu_ticks">自訂CPU時脈</string>
|
<string name="custom_cpu_ticks">自訂CPU時脈</string>
|
||||||
<string name="custom_cpu_ticks_description">自訂CPU時脈。更高的值可能提高效能,但也可能導致遊戲卡死。建議範圍為77-21000。</string>
|
<string name="custom_cpu_ticks_description">自訂CPU時脈。更高的值可能提高效能,但也可能導致遊戲卡死。建議範圍為77-21000。</string>
|
||||||
<string name="cpu_ticks">時脈</string>
|
<string name="cpu_ticks">時脈</string>
|
||||||
@@ -446,41 +428,33 @@
|
|||||||
|
|
||||||
<!-- Network settings strings -->
|
<!-- Network settings strings -->
|
||||||
<string name="web_token">網路令牌</string>
|
<string name="web_token">網路令牌</string>
|
||||||
<string name="web_token_description">用於建立公開大廳的網路令牌。由48個小寫字母a-z組成</string>
|
<string name="web_token_description">用於建立公開大廳的網路令牌。它是由48個小寫字母a-z組成的字串。</string>
|
||||||
<string name="web_username">網路使用者名稱</string>
|
<string name="web_username">網路使用者名稱</string>
|
||||||
<string name="web_username_description">多人遊戲房間中顯示的使用者名稱。必須為4-20個字元,僅能使用英文字母、數字、句點、破折號、底線和空格(標點符號須為英文格式)</string>
|
<string name="web_username_description">多人遊戲房間中顯示的使用者名稱。必須為4-20個字元,僅能使用英文字母、數字、句點、破折號、底線和空格(標點符號須為英文格式)。</string>
|
||||||
<string name="network">網路</string>
|
<string name="network">網路</string>
|
||||||
|
|
||||||
<!-- Graphics settings strings -->
|
<!-- Graphics settings strings -->
|
||||||
<string name="renderer_resolution">解析度 (手提/底座)</string>
|
<string name="renderer_resolution">解析度 (手提/底座)</string>
|
||||||
<string name="renderer_vsync">垂直同步</string>
|
<string name="renderer_vsync">垂直同步</string>
|
||||||
<string name="renderer_scaling_filter">視窗自適應濾波器</string>
|
<string name="renderer_scaling_filter">視窗適應過濾器</string>
|
||||||
<string name="fsr_sharpness">FSR/SGSR 銳化度</string>
|
|
||||||
<string name="fsr_sharpness_description">使用 FSR/SGSR 時圖片的銳化程度</string>
|
|
||||||
<string name="renderer_anti_aliasing">抗鋸齒</string>
|
<string name="renderer_anti_aliasing">抗鋸齒</string>
|
||||||
|
|
||||||
|
|
||||||
<string name="advanced">進階</string>
|
|
||||||
|
|
||||||
<string name="renderer_accuracy">GPU 模式</string>
|
|
||||||
<string name="renderer_accuracy_description">設定 GPU 模擬的準確度。大多數遊戲在設定為快速時即可正常渲染,但有些需要渲染粒子的遊戲仍需設為準確來避免圖形錯誤</string>
|
|
||||||
<string name="dma_accuracy">DMA 準確度</string>
|
<string name="dma_accuracy">DMA 準確度</string>
|
||||||
<string name="dma_accuracy_description">控制 DMA 準確度。將準確度設為穩定可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為預設</string>
|
<string name="dma_accuracy_description">控制 DMA 準確度。安全準確度可以修復某些遊戲中的問題,但在某些情況下也可能影響效能。如果不確定,請保留為「預設」。</string>
|
||||||
<string name="gpu_fence_behavior">GPU 同步柵欄模式</string>
|
|
||||||
<string name="gpu_fence_behavior_description">控制 GPU 同步柵欄模式。即時是速度最快的選項,但可能會導致一些問題。使用平衡可以提供更好的相容性並修復某些遊戲中的錯誤。準確則是在犧牲部分效能的情況下進一步提升相容性。嚴格是最慢的選項,但可以修復那些對同步要求更嚴格的遊戲中的問題。預設則會依照 GPU 準確度設定</string>
|
|
||||||
<string name="anisotropic_filtering">各向異性過濾</string>
|
<string name="anisotropic_filtering">各向異性過濾</string>
|
||||||
<string name="anisotropic_filtering_description">改善斜角檢視時的紋理品質</string>
|
<string name="anisotropic_filtering_description">改善斜角檢視時的紋理品質</string>
|
||||||
<string name="vram_usage_mode">VRAM使用模式</string>
|
<string name="vram_usage_mode">VRAM使用模式</string>
|
||||||
<string name="vram_usage_mode_description">控制GPU記憶體的分配與釋放策略</string>
|
<string name="vram_usage_mode_description">控制GPU記憶體的分配與釋放策略</string>
|
||||||
<string name="accelerate_astc">ASTC解碼方式</string>
|
<string name="accelerate_astc">ASTC解碼方式</string>
|
||||||
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、穩定)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
|
<string name="accelerate_astc_description">選擇ASTC壓縮紋理的解碼方式:CPU(慢速、安全)、GPU(快速、推薦)或CPU非同步(無卡頓,可能導致問題)</string>
|
||||||
|
|
||||||
<string name="sync_memory_operations">同步記憶體操作</string>
|
<string name="sync_memory_operations">同步記憶體操作</string>
|
||||||
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大</string>
|
<string name="sync_memory_operations_description">確保計算和記憶體操作之間的資料一致性。 此選項應能修復某些遊戲中的問題,但在某些情況下可能會降低效能。 使用Unreal Engine 4的遊戲似乎受影響最大。</string>
|
||||||
<string name="use_disk_shader_cache">磁碟著色器快取</string>
|
<string name="use_disk_shader_cache">磁碟著色器快取</string>
|
||||||
<string name="use_disk_shader_cache_description">將產生的著色器快取儲存至硬碟以減少中斷</string>
|
<string name="use_disk_shader_cache_description">將產生的著色器快取儲存至硬碟以減少中斷。</string>
|
||||||
<string name="renderer_force_max_clock">強制使用最大時脈 (僅限Adreno)</string>
|
<string name="renderer_force_max_clock">強制使用最大時脈 (僅限Adreno)</string>
|
||||||
<string name="renderer_force_max_clock_description">強制 GPU 以可能的最大時脈執行 (熱溫限制仍會被套用)</string>
|
<string name="renderer_force_max_clock_description">強制 GPU 以可能的最大時脈執行 (熱溫限制仍會被套用)。</string>
|
||||||
<string name="renderer_reactive_flushing">使用重新啟用排清</string>
|
<string name="renderer_reactive_flushing">使用重新啟用排清</string>
|
||||||
<string name="renderer_reactive_flushing_description">犧牲效能,以改善部分遊戲的轉譯準確度。</string>
|
<string name="renderer_reactive_flushing_description">犧牲效能,以改善部分遊戲的轉譯準確度。</string>
|
||||||
<string name="skip_cpu_inner_invalidation">跳過CPU內部失效處理</string>
|
<string name="skip_cpu_inner_invalidation">跳過CPU內部失效處理</string>
|
||||||
@@ -629,7 +603,7 @@
|
|||||||
<string name="import_complete">導入完成</string>
|
<string name="import_complete">導入完成</string>
|
||||||
<string name="use_global_setting">使用全域設定</string>
|
<string name="use_global_setting">使用全域設定</string>
|
||||||
<string name="operation_completed_successfully">操作已成功完成</string>
|
<string name="operation_completed_successfully">操作已成功完成</string>
|
||||||
<string name="confirm">下載</string>
|
<string name="confirm">確定</string>
|
||||||
<string name="load">載入</string>
|
<string name="load">載入</string>
|
||||||
<string name="save">儲存</string>
|
<string name="save">儲存</string>
|
||||||
|
|
||||||
@@ -847,8 +821,8 @@
|
|||||||
|
|
||||||
<!-- Memory Layouts -->
|
<!-- Memory Layouts -->
|
||||||
<string name="memory_4gb">4GB (推薦)</string>
|
<string name="memory_4gb">4GB (推薦)</string>
|
||||||
<string name="memory_6gb">6GB (不穩定)</string>
|
<string name="memory_6gb">6GB (不安全)</string>
|
||||||
<string name="memory_8gb">8GB (不穩定)</string>
|
<string name="memory_8gb">8GB (不安全)</string>
|
||||||
|
|
||||||
<!--CPU clock speeds-->
|
<!--CPU clock speeds-->
|
||||||
<string name="clock_boost">加速 (1700MHz)</string>
|
<string name="clock_boost">加速 (1700MHz)</string>
|
||||||
@@ -873,8 +847,8 @@
|
|||||||
|
|
||||||
<!-- DMA Accuracy -->
|
<!-- DMA Accuracy -->
|
||||||
<string name="dma_accuracy_default">預設</string>
|
<string name="dma_accuracy_default">預設</string>
|
||||||
<string name="dma_accuracy_unsafe">不穩定</string>
|
<string name="dma_accuracy_unsafe">不安全</string>
|
||||||
<string name="dma_accuracy_safe">穩定</string>
|
<string name="dma_accuracy_safe">安全</string>
|
||||||
|
|
||||||
<string name="vram_usage_conservative">保守</string>
|
<string name="vram_usage_conservative">保守</string>
|
||||||
<string name="vram_usage_aggressive">積極</string>
|
<string name="vram_usage_aggressive">積極</string>
|
||||||
@@ -900,7 +874,7 @@
|
|||||||
|
|
||||||
<!-- CPU Accuracy -->
|
<!-- CPU Accuracy -->
|
||||||
<string name="cpu_accuracy_accurate">高準確度</string>
|
<string name="cpu_accuracy_accurate">高準確度</string>
|
||||||
<string name="cpu_accuracy_unsafe">低準確度(不穩定)</string>
|
<string name="cpu_accuracy_unsafe">低準確度(不安全)</string>
|
||||||
<string name="cpu_accuracy_paranoid">不合理</string>
|
<string name="cpu_accuracy_paranoid">不合理</string>
|
||||||
<string name="cpu_accuracy_debugging">偵錯</string>
|
<string name="cpu_accuracy_debugging">偵錯</string>
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -147,7 +147,7 @@ Result OpusDecoder::DecodeInterleavedForMultiStream(u32* out_data_size, u64* out
|
|||||||
auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
|
auto* header_p{reinterpret_cast<const OpusPacketHeader*>(input_data.data())};
|
||||||
OpusPacketHeader header{ReverseHeader(*header_p)};
|
OpusPacketHeader header{ReverseHeader(*header_p)};
|
||||||
|
|
||||||
LOG_TRACE(Service_Audio, "header size {:#x} input data size {:#x} in_data size {:#x}",
|
LOG_TRACE(Service_Audio, "header size {:#X} input data size 0x{:X} in_data size 0x{:X}",
|
||||||
header.size, input_data.size_bytes(), in_data.size_bytes());
|
header.size, input_data.size_bytes(), in_data.size_bytes());
|
||||||
|
|
||||||
R_UNLESS(in_data.size_bytes() >= header.size &&
|
R_UNLESS(in_data.size_bytes() >= header.size &&
|
||||||
|
|||||||
@@ -369,7 +369,7 @@ Result InfoUpdater::UpdateMixes(MixContext& mix_context, const u32 mix_buffer_co
|
|||||||
if (mix_count < 0 || mix_count > 0x100) {
|
if (mix_count < 0 || mix_count > 0x100) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
Service_Audio,
|
Service_Audio,
|
||||||
"Invalid mix count from dirty parameter: count={}, magic={:#x}, expected_size={}",
|
"Invalid mix count from dirty parameter: count={}, magic=0x{:X}, expected_size={}",
|
||||||
mix_count, in_dirty_params->magic, in_header->mix_size);
|
mix_count, in_dirty_params->magic, in_header->mix_size);
|
||||||
return Service::Audio::ResultInvalidUpdateInfo;
|
return Service::Audio::ResultInvalidUpdateInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
|
// SPDX-FileCopyrightText: 2021 Skyline Team and Contributors
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
@@ -46,13 +43,13 @@ MAP_MEMBER(void)::MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInf
|
|||||||
|
|
||||||
if (virt_end > va_limit) {
|
if (virt_end > va_limit) {
|
||||||
ASSERT_MSG(false,
|
ASSERT_MSG(false,
|
||||||
"Trying to map a block past the VA limit: virt_end: {:#x}, va_limit: {:#x}",
|
"Trying to map a block past the VA limit: virt_end: 0x{:X}, va_limit: 0x{:X}",
|
||||||
virt_end, va_limit);
|
virt_end, va_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
|
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
|
||||||
if (block_end_successor == blocks.begin()) {
|
if (block_end_successor == blocks.begin()) {
|
||||||
ASSERT_MSG(false, "Trying to map a block before the VA start: virt_end: {:#x}", virt_end);
|
ASSERT_MSG(false, "Trying to map a block before the VA start: virt_end: 0x{:X}", virt_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto block_end_predecessor{std::prev(block_end_successor)};
|
auto block_end_predecessor{std::prev(block_end_successor)};
|
||||||
@@ -127,7 +124,7 @@ MAP_MEMBER(void)::MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInf
|
|||||||
|
|
||||||
// Check that the start successor is either the end block or something in between
|
// Check that the start successor is either the end block or something in between
|
||||||
if (block_start_successor->virt > virt_end) {
|
if (block_start_successor->virt > virt_end) {
|
||||||
ASSERT_MSG(false, "Unsorted block in AS map: virt: {:#x}", block_start_successor->virt);
|
ASSERT_MSG(false, "Unsorted block in AS map: virt: 0x{:X}", block_start_successor->virt);
|
||||||
} else if (block_start_successor->virt == virt_end) {
|
} else if (block_start_successor->virt == virt_end) {
|
||||||
// We need to create a new block as there are none spare that we would overwrite
|
// We need to create a new block as there are none spare that we would overwrite
|
||||||
blocks.insert(block_start_successor, Block(virt, phys, extra_info));
|
blocks.insert(block_start_successor, Block(virt, phys, extra_info));
|
||||||
@@ -153,13 +150,13 @@ MAP_MEMBER(void)::UnmapLocked(VaType virt, VaType size) {
|
|||||||
|
|
||||||
if (virt_end > va_limit) {
|
if (virt_end > va_limit) {
|
||||||
ASSERT_MSG(false,
|
ASSERT_MSG(false,
|
||||||
"Trying to map a block past the VA limit: virt_end: {:#x}, va_limit: {:#x}",
|
"Trying to map a block past the VA limit: virt_end: 0x{:X}, va_limit: 0x{:X}",
|
||||||
virt_end, va_limit);
|
virt_end, va_limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
|
auto block_end_successor{std::lower_bound(blocks.begin(), blocks.end(), virt_end)};
|
||||||
if (block_end_successor == blocks.begin()) {
|
if (block_end_successor == blocks.begin()) {
|
||||||
ASSERT_MSG(false, "Trying to unmap a block before the VA start: virt_end: {:#x}",
|
ASSERT_MSG(false, "Trying to unmap a block before the VA start: virt_end: 0x{:X}",
|
||||||
virt_end);
|
virt_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,7 +257,7 @@ MAP_MEMBER(void)::UnmapLocked(VaType virt, VaType size) {
|
|||||||
auto block_start_successor{std::next(block_start_predecessor)};
|
auto block_start_successor{std::next(block_start_predecessor)};
|
||||||
|
|
||||||
if (block_start_successor->virt > virt_end) {
|
if (block_start_successor->virt > virt_end) {
|
||||||
ASSERT_MSG(false, "Unsorted block in AS map: virt: {:#x}", block_start_successor->virt);
|
ASSERT_MSG(false, "Unsorted block in AS map: virt: 0x{:X}", block_start_successor->virt);
|
||||||
} else if (block_start_successor->virt == virt_end) {
|
} else if (block_start_successor->virt == virt_end) {
|
||||||
// There are no blocks between the start and the end that would let us skip inserting a new
|
// There are no blocks between the start and the end that would let us skip inserting a new
|
||||||
// one for head
|
// one for head
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
@@ -15,7 +12,7 @@ std::vector<u8> HexStringToVector(std::string_view str, bool little_endian) {
|
|||||||
for (std::size_t i = str.size() - 2; i <= str.size(); i -= 2)
|
for (std::size_t i = str.size() - 2; i <= str.size(); i -= 2)
|
||||||
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
||||||
} else {
|
} else {
|
||||||
for (std::size_t i = 0; i + 1 < str.size(); i += 2)
|
for (std::size_t i = 0; i < str.size(); i += 2)
|
||||||
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
out[i / 2] = (ToHexNibble(str[i]) << 4) | ToHexNibble(str[i + 1]);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|||||||
@@ -208,12 +208,4 @@ UUID UUID::MakeRandomRFC4122V4() {
|
|||||||
return uuid;
|
return uuid;
|
||||||
}
|
}
|
||||||
|
|
||||||
UUID UUID::MakeRFC4122V5(std::span<u8, 20> sha1) {
|
|
||||||
UUID uuid{};
|
|
||||||
std::memcpy(&uuid.uuid, sha1.data(), sizeof(UUID));
|
|
||||||
uuid.uuid[8] = 0x80 | (uuid.uuid[8] & 0x3F);
|
|
||||||
uuid.uuid[6] = 0x50 | (uuid.uuid[6] & 0xF);
|
|
||||||
return uuid;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Common
|
} // namespace Common
|
||||||
|
|||||||
+20
-16
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -8,7 +5,6 @@
|
|||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <span>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
@@ -90,20 +86,28 @@ struct UUID {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @brief Creates a random UUID.
|
/**
|
||||||
/// @returns A random UUID.
|
* Creates a random UUID.
|
||||||
[[nodiscard]] static UUID MakeRandom();
|
*
|
||||||
|
* @returns A random UUID.
|
||||||
|
*/
|
||||||
|
static UUID MakeRandom();
|
||||||
|
|
||||||
/// @brief Creates a random UUID with a seed.
|
/**
|
||||||
/// @param seed A seed to initialize the Mersenne-Twister RNG
|
* Creates a random UUID with a seed.
|
||||||
/// @returns A random UUID.
|
*
|
||||||
[[nodiscard]] static UUID MakeRandomWithSeed(u32 seed);
|
* @param seed A seed to initialize the Mersenne-Twister RNG
|
||||||
|
*
|
||||||
|
* @returns A random UUID.
|
||||||
|
*/
|
||||||
|
static UUID MakeRandomWithSeed(u32 seed);
|
||||||
|
|
||||||
/// @brief Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
|
/**
|
||||||
/// @returns A random UUID that is RFC 4122 Version 4 compliant.
|
* Creates a random UUID. The generated UUID is RFC 4122 Version 4 compliant.
|
||||||
[[nodiscard]] static UUID MakeRandomRFC4122V4();
|
*
|
||||||
|
* @returns A random UUID that is RFC 4122 Version 4 compliant.
|
||||||
[[nodiscard]] static UUID MakeRFC4122V5(std::span<u8, 20> sha1);
|
*/
|
||||||
|
static UUID MakeRandomRFC4122V4();
|
||||||
|
|
||||||
friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
|
friend constexpr bool operator==(const UUID& lhs, const UUID& rhs) = default;
|
||||||
};
|
};
|
||||||
|
|||||||
+5
-3
@@ -264,7 +264,9 @@ struct System::Impl {
|
|||||||
|
|
||||||
// Setting changes may require a full system reinitialization (e.g., disabling multicore).
|
// Setting changes may require a full system reinitialization (e.g., disabling multicore).
|
||||||
ReinitializeIfNecessary(system);
|
ReinitializeIfNecessary(system);
|
||||||
|
|
||||||
kernel.Initialize();
|
kernel.Initialize();
|
||||||
|
cpu_manager.Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
SystemResultStatus SetupForApplicationProcess(System& system, Frontend::EmuWindow& emu_window) {
|
||||||
@@ -291,7 +293,9 @@ struct System::Impl {
|
|||||||
return SystemResultStatus::Success;
|
return SystemResultStatus::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window, const std::string& filepath, Service::AM::FrontendAppletParameters& params) {
|
SystemResultStatus Load(System& system, Frontend::EmuWindow& emu_window,
|
||||||
|
const std::string& filepath,
|
||||||
|
Service::AM::FrontendAppletParameters& params) {
|
||||||
InitializeKernel(system);
|
InitializeKernel(system);
|
||||||
|
|
||||||
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
|
const auto file = GetGameFileFromPath(virtual_filesystem, filepath);
|
||||||
@@ -338,8 +342,6 @@ struct System::Impl {
|
|||||||
ShutdownMainProcess();
|
ShutdownMainProcess();
|
||||||
return init_result;
|
return init_result;
|
||||||
}
|
}
|
||||||
// Waiting for GPU before initializing CPU
|
|
||||||
cpu_manager.Initialize();
|
|
||||||
|
|
||||||
// Initialize cheat engine
|
// Initialize cheat engine
|
||||||
if (cheat_engine) {
|
if (cheat_engine) {
|
||||||
|
|||||||
@@ -431,7 +431,7 @@ void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, s
|
|||||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
HW_Memory,
|
HW_Memory,
|
||||||
"Unmapped Device ReadBlock @ {:#016x} (start address = {:#016x}, size = {})",
|
"Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
current_vaddr, address, size);
|
current_vaddr, address, size);
|
||||||
std::memset(dest_pointer, 0, copy_amount);
|
std::memset(dest_pointer, 0, copy_amount);
|
||||||
},
|
},
|
||||||
@@ -450,7 +450,7 @@ void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_poin
|
|||||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
HW_Memory,
|
HW_Memory,
|
||||||
"Unmapped Device WriteBlock @ {:#016x} (start address = {:#016x}, size = {})",
|
"Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
current_vaddr, address, size);
|
current_vaddr, address, size);
|
||||||
},
|
},
|
||||||
[&](size_t copy_amount, u8* const dst_ptr) {
|
[&](size_t copy_amount, u8* const dst_ptr) {
|
||||||
@@ -489,7 +489,7 @@ void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_poin
|
|||||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
HW_Memory,
|
HW_Memory,
|
||||||
"Unmapped Device ReadBlock @ {:#016x} (start address = {:#016x}, size = {})",
|
"Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
current_vaddr, address, size);
|
current_vaddr, address, size);
|
||||||
std::memset(dest_pointer, 0, copy_amount);
|
std::memset(dest_pointer, 0, copy_amount);
|
||||||
},
|
},
|
||||||
@@ -509,7 +509,7 @@ void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* sr
|
|||||||
[&](size_t copy_amount, DAddr current_vaddr) {
|
[&](size_t copy_amount, DAddr current_vaddr) {
|
||||||
LOG_ERROR(
|
LOG_ERROR(
|
||||||
HW_Memory,
|
HW_Memory,
|
||||||
"Unmapped Device WriteBlock @ {:#016x} (start address = {:#016x}, size = {})",
|
"Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
|
||||||
current_vaddr, address, size);
|
current_vaddr, address, size);
|
||||||
},
|
},
|
||||||
[&](size_t copy_amount, u8* const dst_ptr) {
|
[&](size_t copy_amount, u8* const dst_ptr) {
|
||||||
|
|||||||
@@ -274,22 +274,23 @@ public:
|
|||||||
explicit NACP(VirtualFile file);
|
explicit NACP(VirtualFile file);
|
||||||
~NACP();
|
~NACP();
|
||||||
|
|
||||||
[[nodiscard]] const LanguageEntry& GetLanguageEntry() const;
|
const LanguageEntry& GetLanguageEntry() const;
|
||||||
[[nodiscard]] std::string GetApplicationName() const;
|
std::string GetApplicationName() const;
|
||||||
[[nodiscard]] std::string GetDeveloperName() const;
|
std::string GetDeveloperName() const;
|
||||||
[[nodiscard]] u64 GetTitleId() const;
|
u64 GetTitleId() const;
|
||||||
[[nodiscard]] u64 GetDLCBaseTitleId() const;
|
u64 GetDLCBaseTitleId() const;
|
||||||
[[nodiscard]] std::string GetVersionString() const;
|
std::string GetVersionString() const;
|
||||||
[[nodiscard]] u64 GetDefaultNormalSaveSize() const;
|
u64 GetDefaultNormalSaveSize() const;
|
||||||
[[nodiscard]] u64 GetDefaultJournalSaveSize() const;
|
u64 GetDefaultJournalSaveSize() const;
|
||||||
[[nodiscard]] u32 GetSupportedLanguages() const;
|
u32 GetSupportedLanguages() const;
|
||||||
[[nodiscard]] std::vector<std::string> GetApplicationNames() const;
|
std::vector<std::string> GetApplicationNames() const;
|
||||||
[[nodiscard]] std::vector<u8> GetRawBytes() const;
|
std::vector<u8> GetRawBytes() const;
|
||||||
[[nodiscard]] bool GetUserAccountSwitchLock() const;
|
bool GetUserAccountSwitchLock() const;
|
||||||
[[nodiscard]] u64 GetDeviceSaveDataSize() const;
|
u64 GetDeviceSaveDataSize() const;
|
||||||
[[nodiscard]] u32 GetParentalControlFlag() const;
|
u32 GetParentalControlFlag() const;
|
||||||
[[nodiscard]] const std::array<u8, 0x20>& GetRatingAge() const;
|
const std::array<u8, 0x20>& GetRatingAge() const;
|
||||||
|
|
||||||
|
private:
|
||||||
RawNACP raw{};
|
RawNACP raw{};
|
||||||
std::vector<LanguageEntry> language_entries;
|
std::vector<LanguageEntry> language_entries;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ void IPSwitchCompiler::Parse() {
|
|||||||
const auto& patch_line = lines[++i];
|
const auto& patch_line = lines[++i];
|
||||||
|
|
||||||
// Patch line may contain comments
|
// Patch line may contain comments
|
||||||
if (StartsWith(patch_line, "//") || StartsWith(patch_line, "#")) {
|
if (StartsWith(patch_line, "//")) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -304,7 +304,7 @@ void IPSwitchCompiler::Parse() {
|
|||||||
|
|
||||||
if (print_values) {
|
if (print_values) {
|
||||||
LOG_INFO(Loader,
|
LOG_INFO(Loader,
|
||||||
"[IPSwitchCompiler ('{}')] - Patching value at offset {:#08x} "
|
"[IPSwitchCompiler ('{}')] - Patching value at offset 0x{:08X} "
|
||||||
"with byte string '{}'",
|
"with byte string '{}'",
|
||||||
patch_text->GetName(), offset, Common::HexToString(replace));
|
patch_text->GetName(), offset, Common::HexToString(replace));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1156,14 +1156,4 @@ PatchManager::Metadata PatchManager::ParseControlNCA(const NCA& nca) const {
|
|||||||
|
|
||||||
return {std::move(nacp), icon_file};
|
return {std::move(nacp), icon_file};
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] PatchManager::Metadata PatchManager::GetMetadataFromBaseOrUpdate(Core::System& system, u64 application_id) noexcept {
|
|
||||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(), system.GetContentProvider()};
|
|
||||||
auto metadata = pm.GetControlMetadata();
|
|
||||||
if (metadata.first != nullptr)
|
|
||||||
return metadata;
|
|
||||||
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(application_id), system.GetFileSystemController(), system.GetContentProvider()};
|
|
||||||
return pm_update.GetControlMetadata();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|||||||
@@ -105,9 +105,6 @@ public:
|
|||||||
// Version of GetControlMetadata that takes an arbitrary NCA
|
// Version of GetControlMetadata that takes an arbitrary NCA
|
||||||
[[nodiscard]] Metadata ParseControlNCA(const NCA& nca) const;
|
[[nodiscard]] Metadata ParseControlNCA(const NCA& nca) const;
|
||||||
|
|
||||||
/// @brief Gets NACP metadata (accounting for any patches or updates)
|
|
||||||
[[nodiscard]] static PatchManager::Metadata GetMetadataFromBaseOrUpdate(Core::System& system, u64 application_id) noexcept;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
[[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
[[nodiscard]] std::vector<VirtualFile> CollectPatches(const std::vector<VirtualDir>& patch_dirs,
|
||||||
const std::string& build_id) const;
|
const std::string& build_id) const;
|
||||||
|
|||||||
@@ -181,11 +181,11 @@ const ProgramMetadata::KernelCapabilityDescriptors& ProgramMetadata::GetKernelCa
|
|||||||
|
|
||||||
void ProgramMetadata::Print() const {
|
void ProgramMetadata::Print() const {
|
||||||
LOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
|
||||||
LOG_DEBUG(Service_FS, "Main thread priority: {:#02x}", npdm_header.main_thread_priority);
|
LOG_DEBUG(Service_FS, "Main thread priority: 0x{:02X}", npdm_header.main_thread_priority);
|
||||||
LOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu);
|
LOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu);
|
||||||
LOG_DEBUG(Service_FS, "Main thread stack size: {:#x} bytes", npdm_header.main_stack_size);
|
LOG_DEBUG(Service_FS, "Main thread stack size: {:#X} bytes", npdm_header.main_stack_size);
|
||||||
LOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
|
LOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
|
||||||
LOG_DEBUG(Service_FS, "Flags: {:#02x}", npdm_header.flags);
|
LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", npdm_header.flags);
|
||||||
LOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
|
LOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
|
||||||
npdm_header.has_64_bit_instructions ? "YES" : "NO");
|
npdm_header.has_64_bit_instructions ? "YES" : "NO");
|
||||||
|
|
||||||
@@ -209,15 +209,15 @@ void ProgramMetadata::Print() const {
|
|||||||
|
|
||||||
// Begin ACID printing (potential perms, signed)
|
// Begin ACID printing (potential perms, signed)
|
||||||
LOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
|
||||||
LOG_DEBUG(Service_FS, "Flags: {:#02x}", acid_header.flags);
|
LOG_DEBUG(Service_FS, "Flags: 0x{:02X}", acid_header.flags);
|
||||||
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.production_flag ? "YES" : "NO");
|
LOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.production_flag ? "YES" : "NO");
|
||||||
LOG_DEBUG(Service_FS, "Title ID Min: {:#016x}", acid_header.title_id_min);
|
LOG_DEBUG(Service_FS, "Title ID Min: 0x{:016X}", acid_header.title_id_min);
|
||||||
LOG_DEBUG(Service_FS, "Title ID Max: {:#016x}", acid_header.title_id_max);
|
LOG_DEBUG(Service_FS, "Title ID Max: 0x{:016X}", acid_header.title_id_max);
|
||||||
LOG_DEBUG(Service_FS, "Filesystem Access: {:#016x}\n", acid_file_access.permissions);
|
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", acid_file_access.permissions);
|
||||||
|
|
||||||
// Begin ACI0 printing (actual perms, unsigned)
|
// Begin ACI0 printing (actual perms, unsigned)
|
||||||
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
|
LOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
|
||||||
LOG_DEBUG(Service_FS, "Title ID: {:#016x}", aci_header.title_id);
|
LOG_DEBUG(Service_FS, "Title ID: 0x{:016X}", aci_header.title_id);
|
||||||
LOG_DEBUG(Service_FS, "Filesystem Access: {:#016x}\n", aci_file_access.permissions);
|
LOG_DEBUG(Service_FS, "Filesystem Access: 0x{:016X}\n", aci_file_access.permissions);
|
||||||
}
|
}
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ constexpr inline SystemArchiveDescriptor GetSystemArchive(u64 title_id) {
|
|||||||
|
|
||||||
VirtualFile SynthesizeSystemArchive(const u64 title_id) {
|
VirtualFile SynthesizeSystemArchive(const u64 title_id) {
|
||||||
auto const desc = GetSystemArchive(title_id);
|
auto const desc = GetSystemArchive(title_id);
|
||||||
LOG_INFO(Service_FS, "Synthesizing system archive '{}' ({:#016x}).", desc.name, title_id);
|
LOG_INFO(Service_FS, "Synthesizing system archive '{}' (0x{:016X}).", desc.name, title_id);
|
||||||
if (desc.supplier != nullptr) {
|
if (desc.supplier != nullptr) {
|
||||||
if (auto const dir = desc.supplier(); dir != nullptr) {
|
if (auto const dir = desc.supplier(); dir != nullptr) {
|
||||||
if (auto const romfs = CreateRomFS(dir); romfs != nullptr) {
|
if (auto const romfs = CreateRomFS(dir); romfs != nullptr) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace Kernel::Svc {
|
|||||||
/// Sets the thread activity
|
/// Sets the thread activity
|
||||||
Result SetThreadActivity(Core::System& system, Handle thread_handle,
|
Result SetThreadActivity(Core::System& system, Handle thread_handle,
|
||||||
ThreadActivity thread_activity) {
|
ThreadActivity thread_activity) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, handle={:#08x}, activity={:#08x}", thread_handle,
|
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
|
||||||
thread_activity);
|
thread_activity);
|
||||||
|
|
||||||
// Validate the activity.
|
// Validate the activity.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -43,7 +43,7 @@ constexpr bool IsValidArbitrationType(Svc::ArbitrationType type) {
|
|||||||
// Wait for an address (via Address Arbiter)
|
// Wait for an address (via Address Arbiter)
|
||||||
Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_type, s32 value,
|
Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_type, s32 value,
|
||||||
s64 timeout_ns) {
|
s64 timeout_ns) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, address={:#x}, arb_type={:#x}, value={:#x}, timeout_ns={}",
|
LOG_TRACE(Kernel_SVC, "called, address={:#X}, arb_type=0x{:X}, value=0x{:X}, timeout_ns={}",
|
||||||
address, arb_type, value, timeout_ns);
|
address, arb_type, value, timeout_ns);
|
||||||
|
|
||||||
// Validate input.
|
// Validate input.
|
||||||
@@ -74,7 +74,7 @@ Result WaitForAddress(Core::System& system, u64 address, ArbitrationType arb_typ
|
|||||||
// Signals to an address (via Address Arbiter)
|
// Signals to an address (via Address Arbiter)
|
||||||
Result SignalToAddress(Core::System& system, u64 address, SignalType signal_type, s32 value,
|
Result SignalToAddress(Core::System& system, u64 address, SignalType signal_type, s32 value,
|
||||||
s32 count) {
|
s32 count) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, address={:#x}, signal_type={:#x}, value={:#x}, count={:#x}",
|
LOG_TRACE(Kernel_SVC, "called, address={:#X}, signal_type=0x{:X}, value=0x{:X}, count=0x{:X}",
|
||||||
address, signal_type, value, count);
|
address, signal_type, value, count);
|
||||||
|
|
||||||
// Validate input.
|
// Validate input.
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ constexpr bool IsValidUnmapFromOwnerCodeMemoryPermission(MemoryPermission perm)
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) {
|
Result CreateCodeMemory(Core::System& system, Handle* out, u64 address, uint64_t size) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, address={:#x}, size={:#x}", address, size);
|
LOG_TRACE(Kernel_SVC, "called, address={:#X}, size=0x{:X}", address, size);
|
||||||
|
|
||||||
// Validate address / size.
|
// Validate address / size.
|
||||||
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
|
R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
|
||||||
@@ -69,8 +69,8 @@ Result ControlCodeMemory(Core::System& system, Handle code_memory_handle,
|
|||||||
MemoryPermission perm) {
|
MemoryPermission perm) {
|
||||||
|
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
"called, code_memory_handle={:#x}, operation={:#x}, address={:#x}, size={:#x}, "
|
"called, code_memory_handle={:#X}, operation=0x{:X}, address=0x{:X}, size=0x{:X}, "
|
||||||
"permission={:#x}",
|
"permission={:#X}",
|
||||||
code_memory_handle, operation, address, size, perm);
|
code_memory_handle, operation, address, size, perm);
|
||||||
|
|
||||||
// Validate the address / size.
|
// Validate the address / size.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -17,7 +17,7 @@ namespace Kernel::Svc {
|
|||||||
/// Wait process wide key atomic
|
/// Wait process wide key atomic
|
||||||
Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u32 tag,
|
Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u32 tag,
|
||||||
s64 timeout_ns) {
|
s64 timeout_ns) {
|
||||||
LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag={:#08x}, timeout_ns={}", address,
|
LOG_TRACE(Kernel_SVC, "called address={:X}, cv_key={:X}, tag=0x{:08X}, timeout_ns={}", address,
|
||||||
cv_key, tag, timeout_ns);
|
cv_key, tag, timeout_ns);
|
||||||
|
|
||||||
// Validate input.
|
// Validate input.
|
||||||
@@ -48,7 +48,7 @@ Result WaitProcessWideKeyAtomic(Core::System& system, u64 address, u64 cv_key, u
|
|||||||
|
|
||||||
/// Signal process wide key
|
/// Signal process wide key
|
||||||
void SignalProcessWideKey(Core::System& system, u64 cv_key, s32 count) {
|
void SignalProcessWideKey(Core::System& system, u64 cv_key, s32 count) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, cv_key={:#x}, count={:#08x}", cv_key, count);
|
LOG_TRACE(Kernel_SVC, "called, cv_key={:#X}, count=0x{:08X}", cv_key, count);
|
||||||
|
|
||||||
// Signal the condition variable.
|
// Signal the condition variable.
|
||||||
return GetCurrentProcess(system.Kernel())
|
return GetCurrentProcess(system.Kernel())
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
namespace Kernel::Svc {
|
namespace Kernel::Svc {
|
||||||
|
|
||||||
Result SignalEvent(Core::System& system, Handle event_handle) {
|
Result SignalEvent(Core::System& system, Handle event_handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, event_handle={:#08x}", event_handle);
|
LOG_DEBUG(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
|
||||||
|
|
||||||
// Get the current handle table.
|
// Get the current handle table.
|
||||||
const KHandleTable& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const KHandleTable& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
@@ -26,7 +26,7 @@ Result SignalEvent(Core::System& system, Handle event_handle) {
|
|||||||
if (event.IsNotNull()) {
|
if (event.IsNotNull()) {
|
||||||
event->Signal(system.Kernel());
|
event->Signal(system.Kernel());
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(Kernel_SVC, "SignalEvent best-effort unknown handle={:#08x} (ignored)",
|
LOG_WARNING(Kernel_SVC, "SignalEvent best-effort unknown handle=0x{:08X} (ignored)",
|
||||||
event_handle);
|
event_handle);
|
||||||
}
|
}
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -41,7 +41,7 @@ Result SignalEvent(Core::System& system, Handle event_handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result ClearEvent(Core::System& system, Handle event_handle) {
|
Result ClearEvent(Core::System& system, Handle event_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, event_handle={:#08x}", event_handle);
|
LOG_TRACE(Kernel_SVC, "called, event_handle=0x{:08X}", event_handle);
|
||||||
|
|
||||||
// Get the current handle table.
|
// Get the current handle table.
|
||||||
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <cctype>
|
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/debugger/debugger.h"
|
#include "core/debugger/debugger.h"
|
||||||
#include "core/hle/kernel/k_process.h"
|
#include "core/hle/kernel/k_process.h"
|
||||||
@@ -42,7 +41,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
|||||||
std::string hexdump;
|
std::string hexdump;
|
||||||
for (std::size_t i = 0; i < debug_buffer.size(); i++) {
|
for (std::size_t i = 0; i < debug_buffer.size(); i++) {
|
||||||
hexdump += fmt::format("{:02X} ", debug_buffer[i]);
|
hexdump += fmt::format("{:02X} ", debug_buffer[i]);
|
||||||
if ((i + 1) % 32 == 0) {
|
if (i != 0 && i % 16 == 0) {
|
||||||
hexdump += '\n';
|
hexdump += '\n';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,35 +51,35 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
|||||||
};
|
};
|
||||||
switch (break_reason) {
|
switch (break_reason) {
|
||||||
case BreakReason::Panic:
|
case BreakReason::Panic:
|
||||||
LOG_CRITICAL(Debug_Emulated, "Userspace PANIC! info1={:#016x}, info2={:#016x}", info1,
|
LOG_CRITICAL(Debug_Emulated, "Userspace PANIC! info1=0x{:016X}, info2=0x{:016X}", info1,
|
||||||
info2);
|
info2);
|
||||||
handle_debug_buffer(info1, info2);
|
handle_debug_buffer(info1, info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::Assert:
|
case BreakReason::Assert:
|
||||||
LOG_CRITICAL(Debug_Emulated, "Userspace Assertion failed! info1={:#016x}, info2={:#016x}",
|
LOG_CRITICAL(Debug_Emulated, "Userspace Assertion failed! info1=0x{:016X}, info2=0x{:016X}",
|
||||||
info1, info2);
|
info1, info2);
|
||||||
handle_debug_buffer(info1, info2);
|
handle_debug_buffer(info1, info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::User:
|
case BreakReason::User:
|
||||||
LOG_WARNING(Debug_Emulated, "Userspace Break! {:#016x} with size {:#016x}", info1, info2);
|
LOG_WARNING(Debug_Emulated, "Userspace Break! 0x{:016X} with size 0x{:016X}", info1, info2);
|
||||||
handle_debug_buffer(info1, info2);
|
handle_debug_buffer(info1, info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::PreLoadDll:
|
case BreakReason::PreLoadDll:
|
||||||
LOG_INFO(Debug_Emulated,
|
LOG_INFO(Debug_Emulated,
|
||||||
"Userspace Attempting to load an NRO at {:#016x} with size {:#016x}", info1,
|
"Userspace Attempting to load an NRO at 0x{:016X} with size 0x{:016X}", info1,
|
||||||
info2);
|
info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::PostLoadDll:
|
case BreakReason::PostLoadDll:
|
||||||
LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at {:#016x} with size {:#016x}", info1,
|
LOG_INFO(Debug_Emulated, "Userspace Loaded an NRO at 0x{:016X} with size 0x{:016X}", info1,
|
||||||
info2);
|
info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::PreUnloadDll:
|
case BreakReason::PreUnloadDll:
|
||||||
LOG_INFO(Debug_Emulated,
|
LOG_INFO(Debug_Emulated,
|
||||||
"Userspace Attempting to unload an NRO at {:#016x} with size {:#016x}", info1,
|
"Userspace Attempting to unload an NRO at 0x{:016X} with size 0x{:016X}", info1,
|
||||||
info2);
|
info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::PostUnloadDll:
|
case BreakReason::PostUnloadDll:
|
||||||
LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at {:#016x} with size {:#016x}",
|
LOG_INFO(Debug_Emulated, "Userspace Unloaded an NRO at 0x{:016X} with size 0x{:016X}",
|
||||||
info1, info2);
|
info1, info2);
|
||||||
break;
|
break;
|
||||||
case BreakReason::CppException:
|
case BreakReason::CppException:
|
||||||
@@ -89,7 +88,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
|||||||
default:
|
default:
|
||||||
LOG_WARNING(
|
LOG_WARNING(
|
||||||
Debug_Emulated,
|
Debug_Emulated,
|
||||||
"Signalling debugger, Unknown break reason {:#x}, info1={:#016x}, info2={:#016x}",
|
"Signalling debugger, Unknown break reason {:#X}, info1=0x{:016X}, info2=0x{:016X}",
|
||||||
reason, info1, info2);
|
reason, info1, info2);
|
||||||
handle_debug_buffer(info1, info2);
|
handle_debug_buffer(info1, info2);
|
||||||
break;
|
break;
|
||||||
@@ -102,7 +101,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
|||||||
if (!notification_only) {
|
if (!notification_only) {
|
||||||
LOG_CRITICAL(
|
LOG_CRITICAL(
|
||||||
Debug_Emulated,
|
Debug_Emulated,
|
||||||
"Emulated program broke execution! reason={:#016x}, info1={:#016x}, info2={:#016x}",
|
"Emulated program broke execution! reason=0x{:016X}, info1=0x{:016X}, info2=0x{:016X}",
|
||||||
reason, info1, info2);
|
reason, info1, info2);
|
||||||
|
|
||||||
handle_debug_buffer(info1, info2);
|
handle_debug_buffer(info1, info2);
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ namespace Kernel::Svc {
|
|||||||
/// Gets system/memory information for the current process
|
/// Gets system/memory information for the current process
|
||||||
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
|
Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle handle,
|
||||||
u64 info_sub_id) {
|
u64 info_sub_id) {
|
||||||
LOG_TRACE(Kernel_SVC, "called info_id={:#x}, info_sub_id={:#x}, handle={:#08x}",
|
LOG_TRACE(Kernel_SVC, "called info_id={:#X}, info_sub_id=0x{:X}, handle=0x{:08X}",
|
||||||
info_id_type, info_sub_id, handle);
|
info_id_type, info_sub_id, handle);
|
||||||
|
|
||||||
u32 info_id = static_cast<u32>(info_id_type);
|
u32 info_id = static_cast<u32>(info_id_type);
|
||||||
@@ -153,7 +153,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id={:#016x}", info_id);
|
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
|
||||||
R_THROW(ResultInvalidEnumValue);
|
R_THROW(ResultInvalidEnumValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,7 +206,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
.GetHandleTable()
|
.GetHandleTable()
|
||||||
.GetObject<KThread>(system.Kernel(), Handle(handle));
|
.GetObject<KThread>(system.Kernel(), Handle(handle));
|
||||||
if (thread.IsNull()) {
|
if (thread.IsNull()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle={:#08x}",
|
LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
|
||||||
static_cast<Handle>(handle));
|
static_cast<Handle>(handle));
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
@@ -265,7 +265,7 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
|||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id={:#016x}", info_id);
|
LOG_ERROR(Kernel_SVC, "Unimplemented svcGetInfo id=0x{:016X}", info_id);
|
||||||
R_THROW(ResultInvalidEnumValue);
|
R_THROW(ResultInvalidEnumValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -13,7 +13,7 @@ namespace Kernel::Svc {
|
|||||||
|
|
||||||
/// Attempts to locks a mutex
|
/// Attempts to locks a mutex
|
||||||
Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u32 tag) {
|
Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u32 tag) {
|
||||||
LOG_TRACE(Kernel_SVC, "called thread_handle={:#08x}, address={:#x}, tag={:#08x}",
|
LOG_TRACE(Kernel_SVC, "called thread_handle=0x{:08X}, address={:#X}, tag=0x{:08X}",
|
||||||
thread_handle, address, tag);
|
thread_handle, address, tag);
|
||||||
|
|
||||||
// Validate the input address.
|
// Validate the input address.
|
||||||
@@ -25,7 +25,7 @@ Result ArbitrateLock(Core::System& system, Handle thread_handle, u64 address, u3
|
|||||||
|
|
||||||
/// Unlock a mutex
|
/// Unlock a mutex
|
||||||
Result ArbitrateUnlock(Core::System& system, u64 address) {
|
Result ArbitrateUnlock(Core::System& system, u64 address) {
|
||||||
LOG_TRACE(Kernel_SVC, "called address={:#x}", address);
|
LOG_TRACE(Kernel_SVC, "called address={:#X}", address);
|
||||||
|
|
||||||
// Validate the input address.
|
// Validate the input address.
|
||||||
R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory);
|
R_UNLESS(!IsKernelAddress(address), ResultInvalidCurrentMemory);
|
||||||
|
|||||||
@@ -34,12 +34,12 @@ constexpr bool IsValidAddressRange(u64 address, u64 size) {
|
|||||||
// in the same order.
|
// in the same order.
|
||||||
Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr, u64 src_addr, u64 size) {
|
Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr, u64 src_addr, u64 size) {
|
||||||
if (!Common::IsAligned(dst_addr, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(dst_addr, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, {:#016X}", dst_addr);
|
LOG_ERROR(Kernel_SVC, "Destination address is not aligned to 4KB, 0x{:016X}", dst_addr);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::IsAligned(src_addr, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(src_addr, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Source address is not aligned to 4KB, {:#016X}", src_addr);
|
LOG_ERROR(Kernel_SVC, "Source address is not aligned to 4KB, 0x{:016X}", src_addr);
|
||||||
R_THROW(ResultInvalidSize);
|
R_THROW(ResultInvalidSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,26 +49,26 @@ Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, {:#016X}", size);
|
LOG_ERROR(Kernel_SVC, "Size is not aligned to 4KB, 0x{:016X}", size);
|
||||||
R_THROW(ResultInvalidSize);
|
R_THROW(ResultInvalidSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_addr, size)) {
|
if (!IsValidAddressRange(dst_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination is not a valid address range, addr={:#016x}, size={:#016x}",
|
"Destination is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
||||||
dst_addr, size);
|
dst_addr, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_addr, size)) {
|
if (!IsValidAddressRange(src_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr={:#016x}, size={:#016x}",
|
LOG_ERROR(Kernel_SVC, "Source is not a valid address range, addr=0x{:016X}, size=0x{:016X}",
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!manager.Contains(src_addr, size)) {
|
if (!manager.Contains(src_addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source is not within the address space, addr={:#016x}, size={:#016x}",
|
"Source is not within the address space, addr=0x{:016X}, size=0x{:016X}",
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ Result MapUnmapMemorySanityChecks(const KProcessPageTable& manager, u64 dst_addr
|
|||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPermission perm) {
|
Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPermission perm) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, address={:#016x}, size={:#x}, perm={:#08x}", address, size,
|
LOG_DEBUG(Kernel_SVC, "called, address=0x{:016X}, size={:#X}, perm=0x{:08X}", address, size,
|
||||||
perm);
|
perm);
|
||||||
|
|
||||||
// Validate address / size.
|
// Validate address / size.
|
||||||
@@ -101,7 +101,7 @@ Result SetMemoryPermission(Core::System& system, u64 address, u64 size, MemoryPe
|
|||||||
|
|
||||||
Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, u32 attr) {
|
Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask, u32 attr) {
|
||||||
LOG_DEBUG(Kernel_SVC,
|
LOG_DEBUG(Kernel_SVC,
|
||||||
"called, address={:#016x}, size={:#x}, mask={:#08x}, attribute={:#08x}", address,
|
"called, address=0x{:016X}, size={:#X}, mask=0x{:08X}, attribute=0x{:08X}", address,
|
||||||
size, mask, attr);
|
size, mask, attr);
|
||||||
|
|
||||||
// Validate address / size.
|
// Validate address / size.
|
||||||
@@ -132,7 +132,7 @@ Result SetMemoryAttribute(Core::System& system, u64 address, u64 size, u32 mask,
|
|||||||
|
|
||||||
/// Maps a memory range into a different range.
|
/// Maps a memory range into a different range.
|
||||||
Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, dst_addr={:#x}, src_addr={:#x}, size={:#x}", dst_addr,
|
LOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
|
|
||||||
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
||||||
@@ -147,7 +147,7 @@ Result MapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
|||||||
|
|
||||||
/// Unmaps a region that was previously mapped with svcMapMemory
|
/// Unmaps a region that was previously mapped with svcMapMemory
|
||||||
Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
Result UnmapMemory(Core::System& system, u64 dst_addr, u64 src_addr, u64 size) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, dst_addr={:#x}, src_addr={:#x}, size={:#x}", dst_addr,
|
LOG_TRACE(Kernel_SVC, "called, dst_addr={:#X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
|
||||||
src_addr, size);
|
src_addr, size);
|
||||||
|
|
||||||
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
auto& page_table{GetCurrentProcess(system.Kernel()).GetPageTable()};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace Kernel::Svc {
|
|||||||
|
|
||||||
/// Set the process heap to a given Size. It can both extend and shrink the heap.
|
/// Set the process heap to a given Size. It can both extend and shrink the heap.
|
||||||
Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
|
Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, heap_size={:#x}", size);
|
LOG_TRACE(Kernel_SVC, "called, heap_size={:#X}", size);
|
||||||
|
|
||||||
// Validate size.
|
// Validate size.
|
||||||
R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
|
R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
|
||||||
@@ -31,10 +31,10 @@ Result SetHeapSize(Core::System& system, u64* out_address, u64 size) {
|
|||||||
|
|
||||||
/// Maps memory at a desired address
|
/// Maps memory at a desired address
|
||||||
Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, addr={:#016x}, size={:#x}", addr, size);
|
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size={:#X}", addr, size);
|
||||||
|
|
||||||
if (!Common::IsAligned(addr, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(addr, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, {:#016X}", addr);
|
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,14 +63,14 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
|||||||
|
|
||||||
if (!page_table.Contains(addr, size)) {
|
if (!page_table.Contains(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the address space, addr={:#016x}, size={:#016x}", addr,
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
R_THROW(ResultInvalidMemoryRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInAliasRegion(addr, size)) {
|
if (!page_table.IsInAliasRegion(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the alias region, addr={:#016x}, size={:#016x}", addr,
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
R_THROW(ResultInvalidMemoryRegion);
|
||||||
}
|
}
|
||||||
@@ -80,10 +80,10 @@ Result MapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
|||||||
|
|
||||||
/// Unmaps memory previously mapped via MapPhysicalMemory
|
/// Unmaps memory previously mapped via MapPhysicalMemory
|
||||||
Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, addr={:#016x}, size={:#x}", addr, size);
|
LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size={:#X}", addr, size);
|
||||||
|
|
||||||
if (!Common::IsAligned(addr, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(addr, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, {:#016X}", addr);
|
LOG_ERROR(Kernel_SVC, "Address is not aligned to 4KB, 0x{:016X}", addr);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,14 +112,14 @@ Result UnmapPhysicalMemory(Core::System& system, u64 addr, u64 size) {
|
|||||||
|
|
||||||
if (!page_table.Contains(addr, size)) {
|
if (!page_table.Contains(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the address space, addr={:#016x}, size={:#016x}", addr,
|
"Address is not within the address space, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
R_THROW(ResultInvalidMemoryRegion);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!page_table.IsInAliasRegion(addr, size)) {
|
if (!page_table.IsInAliasRegion(addr, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Address is not within the alias region, addr={:#016x}, size={:#016x}", addr,
|
"Address is not within the alias region, addr=0x{:016X}, size=0x{:016X}", addr,
|
||||||
size);
|
size);
|
||||||
R_THROW(ResultInvalidMemoryRegion);
|
R_THROW(ResultInvalidMemoryRegion);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ void ExitProcess(Core::System& system) {
|
|||||||
|
|
||||||
/// Gets the ID of the specified process or a specified thread's owning process.
|
/// Gets the ID of the specified process or a specified thread's owning process.
|
||||||
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
|
Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called handle={:#08x}", handle);
|
LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle);
|
||||||
|
|
||||||
// Get the object from the handle table.
|
// Get the object from the handle table.
|
||||||
KScopedAutoObject obj = GetCurrentProcess(system.Kernel())
|
KScopedAutoObject obj = GetCurrentProcess(system.Kernel())
|
||||||
@@ -55,7 +55,7 @@ Result GetProcessId(Core::System& system, u64* out_process_id, Handle handle) {
|
|||||||
|
|
||||||
Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_process_ids,
|
Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_process_ids,
|
||||||
int32_t out_process_ids_size) {
|
int32_t out_process_ids_size) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called. out_process_ids={:#016x}, out_process_ids_size={}",
|
LOG_DEBUG(Kernel_SVC, "called. out_process_ids=0x{:016X}, out_process_ids_size={}",
|
||||||
out_process_ids, out_process_ids_size);
|
out_process_ids, out_process_ids_size);
|
||||||
|
|
||||||
// If the supplied size is negative or greater than INT32_MAX / sizeof(u64), bail.
|
// If the supplied size is negative or greater than INT32_MAX / sizeof(u64), bail.
|
||||||
@@ -71,7 +71,7 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
|
|||||||
|
|
||||||
if (out_process_ids_size > 0 &&
|
if (out_process_ids_size > 0 &&
|
||||||
!GetCurrentProcess(kernel).GetPageTable().Contains(out_process_ids, total_copy_size)) {
|
!GetCurrentProcess(kernel).GetPageTable().Contains(out_process_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin={:#016x}, end={:#016x}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_process_ids, out_process_ids + total_copy_size);
|
out_process_ids, out_process_ids + total_copy_size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
@@ -95,12 +95,12 @@ Result GetProcessList(Core::System& system, s32* out_num_processes, u64 out_proc
|
|||||||
|
|
||||||
Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle,
|
Result GetProcessInfo(Core::System& system, s64* out, Handle process_handle,
|
||||||
ProcessInfoType info_type) {
|
ProcessInfoType info_type) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, handle={:#08x}, type={:#x}", process_handle, info_type);
|
LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, type={:#X}", process_handle, info_type);
|
||||||
|
|
||||||
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
||||||
if (process.IsNull()) {
|
if (process.IsNull()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle={:#08x}",
|
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
|
||||||
process_handle);
|
process_handle);
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ constexpr bool IsValidProcessMemoryPermission(Svc::MemoryPermission perm) {
|
|||||||
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u64 address,
|
Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u64 address,
|
||||||
u64 size, Svc::MemoryPermission perm) {
|
u64 size, Svc::MemoryPermission perm) {
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
"called, process_handle={:#x}, addr={:#x}, size={:#x}, permissions={:#08x}",
|
"called, process_handle={:#X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
|
||||||
process_handle, address, size, perm);
|
process_handle, address, size, perm);
|
||||||
|
|
||||||
// Validate the address/size.
|
// Validate the address/size.
|
||||||
@@ -62,7 +62,7 @@ Result SetProcessMemoryPermission(Core::System& system, Handle process_handle, u
|
|||||||
Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
|
Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
|
||||||
u64 src_address, u64 size) {
|
u64 src_address, u64 size) {
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
"called, dst_address={:#x}, process_handle={:#x}, src_address={:#x}, size={:#x}",
|
"called, dst_address={:#X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
|
||||||
dst_address, process_handle, src_address, size);
|
dst_address, process_handle, src_address, size);
|
||||||
|
|
||||||
// Validate the address/size.
|
// Validate the address/size.
|
||||||
@@ -103,7 +103,7 @@ Result MapProcessMemory(Core::System& system, u64 dst_address, Handle process_ha
|
|||||||
Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
|
Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_handle,
|
||||||
u64 src_address, u64 size) {
|
u64 src_address, u64 size) {
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
"called, dst_address={:#x}, process_handle={:#x}, src_address={:#x}, size={:#x}",
|
"called, dst_address={:#X}, process_handle=0x{:X}, src_address=0x{:X}, size=0x{:X}",
|
||||||
dst_address, process_handle, src_address, size);
|
dst_address, process_handle, src_address, size);
|
||||||
|
|
||||||
// Validate the address/size.
|
// Validate the address/size.
|
||||||
@@ -136,39 +136,39 @@ Result UnmapProcessMemory(Core::System& system, u64 dst_address, Handle process_
|
|||||||
Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
|
Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
|
||||||
u64 src_address, u64 size) {
|
u64 src_address, u64 size) {
|
||||||
LOG_DEBUG(Kernel_SVC,
|
LOG_DEBUG(Kernel_SVC,
|
||||||
"called. process_handle={:#08x}, dst_address={:#016x}, "
|
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, "
|
||||||
"src_address={:#016x}, size={:#016x}",
|
"src_address=0x{:016X}, size=0x{:016X}",
|
||||||
process_handle, dst_address, src_address, size);
|
process_handle, dst_address, src_address, size);
|
||||||
|
|
||||||
if (!Common::IsAligned(src_address, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(src_address, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address={:#016X}).",
|
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
||||||
src_address);
|
src_address);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::IsAligned(dst_address, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(dst_address, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address={:#016X}).",
|
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
||||||
dst_address);
|
dst_address);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0 || !Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE)) {
|
if (size == 0 || !Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size={:#016X})", size);
|
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X})", size);
|
||||||
R_THROW(ResultInvalidSize);
|
R_THROW(ResultInvalidSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_address, size)) {
|
if (!IsValidAddressRange(dst_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination address range overflows the address space (dst_address={:#016x}, "
|
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
||||||
"size={:#016x}).",
|
"size=0x{:016X}).",
|
||||||
dst_address, size);
|
dst_address, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_address, size)) {
|
if (!IsValidAddressRange(src_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source address range overflows the address space (src_address={:#016x}, "
|
"Source address range overflows the address space (src_address=0x{:016X}, "
|
||||||
"size={:#016x}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
@@ -176,7 +176,7 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
|
|||||||
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
||||||
if (process.IsNull()) {
|
if (process.IsNull()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle={:#08x}).",
|
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
||||||
process_handle);
|
process_handle);
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
@@ -184,8 +184,8 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
|
|||||||
auto& page_table = process->GetPageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
if (!page_table.Contains(src_address, size)) {
|
if (!page_table.Contains(src_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source address range is not within the address space (src_address={:#016x}, "
|
"Source address range is not within the address space (src_address=0x{:016X}, "
|
||||||
"size={:#016x}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
@@ -197,39 +197,39 @@ Result MapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst
|
|||||||
Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
|
Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 dst_address,
|
||||||
u64 src_address, u64 size) {
|
u64 src_address, u64 size) {
|
||||||
LOG_DEBUG(Kernel_SVC,
|
LOG_DEBUG(Kernel_SVC,
|
||||||
"called. process_handle={:#08x}, dst_address={:#016x}, src_address={:#016x}, "
|
"called. process_handle=0x{:08X}, dst_address=0x{:016X}, src_address=0x{:016X}, "
|
||||||
"size={:#016x}",
|
"size=0x{:016X}",
|
||||||
process_handle, dst_address, src_address, size);
|
process_handle, dst_address, src_address, size);
|
||||||
|
|
||||||
if (!Common::IsAligned(dst_address, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(dst_address, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address={:#016X}).",
|
LOG_ERROR(Kernel_SVC, "dst_address is not page-aligned (dst_address=0x{:016X}).",
|
||||||
dst_address);
|
dst_address);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Common::IsAligned(src_address, Core::Memory::YUZU_PAGESIZE)) {
|
if (!Common::IsAligned(src_address, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address={:#016X}).",
|
LOG_ERROR(Kernel_SVC, "src_address is not page-aligned (src_address=0x{:016X}).",
|
||||||
src_address);
|
src_address);
|
||||||
R_THROW(ResultInvalidAddress);
|
R_THROW(ResultInvalidAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (size == 0 || !Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE)) {
|
if (size == 0 || !Common::IsAligned(size, Core::Memory::YUZU_PAGESIZE)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size={:#016X}).", size);
|
LOG_ERROR(Kernel_SVC, "Size is zero or not page-aligned (size=0x{:016X}).", size);
|
||||||
R_THROW(ResultInvalidSize);
|
R_THROW(ResultInvalidSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(dst_address, size)) {
|
if (!IsValidAddressRange(dst_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Destination address range overflows the address space (dst_address={:#016x}, "
|
"Destination address range overflows the address space (dst_address=0x{:016X}, "
|
||||||
"size={:#016x}).",
|
"size=0x{:016X}).",
|
||||||
dst_address, size);
|
dst_address, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidAddressRange(src_address, size)) {
|
if (!IsValidAddressRange(src_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source address range overflows the address space (src_address={:#016x}, "
|
"Source address range overflows the address space (src_address=0x{:016X}, "
|
||||||
"size={:#016x}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
@@ -237,7 +237,7 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
|
|||||||
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
||||||
if (process.IsNull()) {
|
if (process.IsNull()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle={:#08x}).",
|
LOG_ERROR(Kernel_SVC, "Invalid process handle specified (handle=0x{:08X}).",
|
||||||
process_handle);
|
process_handle);
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
@@ -245,8 +245,8 @@ Result UnmapProcessCodeMemory(Core::System& system, Handle process_handle, u64 d
|
|||||||
auto& page_table = process->GetPageTable();
|
auto& page_table = process->GetPageTable();
|
||||||
if (!page_table.Contains(src_address, size)) {
|
if (!page_table.Contains(src_address, size)) {
|
||||||
LOG_ERROR(Kernel_SVC,
|
LOG_ERROR(Kernel_SVC,
|
||||||
"Source address range is not within the address space (src_address={:#016x}, "
|
"Source address range is not within the address space (src_address=0x{:016X}, "
|
||||||
"size={:#016x}).",
|
"size=0x{:016X}).",
|
||||||
src_address, size);
|
src_address, size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ namespace Kernel::Svc {
|
|||||||
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
|
Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
|
||||||
u64 query_address) {
|
u64 query_address) {
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
"called, out_memory_info={:#016x}, "
|
"called, out_memory_info=0x{:016X}, "
|
||||||
"query_address={:#016x}",
|
"query_address=0x{:016X}",
|
||||||
out_memory_info, query_address);
|
out_memory_info, query_address);
|
||||||
|
|
||||||
// Query memory is just QueryProcessMemory on the current process.
|
// Query memory is just QueryProcessMemory on the current process.
|
||||||
@@ -24,11 +24,11 @@ Result QueryMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out
|
|||||||
|
|
||||||
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
|
Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageInfo* out_page_info,
|
||||||
Handle process_handle, uint64_t address) {
|
Handle process_handle, uint64_t address) {
|
||||||
LOG_TRACE(Kernel_SVC, "called process={:#08x} address={:X}", process_handle, address);
|
LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
|
||||||
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
KScopedAutoObject process = handle_table.GetObject<KProcess>(system.Kernel(), process_handle);
|
||||||
if (process.IsNull()) {
|
if (process.IsNull()) {
|
||||||
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle={:#08x}",
|
LOG_ERROR(Kernel_SVC, "Process handle does not exist, process_handle=0x{:08X}",
|
||||||
process_handle);
|
process_handle);
|
||||||
R_THROW(ResultInvalidHandle);
|
R_THROW(ResultInvalidHandle);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ constexpr bool IsValidSharedMemoryPermission(MemoryPermission perm) {
|
|||||||
Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u64 size,
|
Result MapSharedMemory(Core::System& system, Handle shmem_handle, u64 address, u64 size,
|
||||||
Svc::MemoryPermission map_perm) {
|
Svc::MemoryPermission map_perm) {
|
||||||
LOG_TRACE(Kernel_SVC,
|
LOG_TRACE(Kernel_SVC,
|
||||||
"called, shared_memory_handle={:#x}, addr={:#x}, size={:#x}, permissions={:#08x}",
|
"called, shared_memory_handle={:#X}, addr=0x{:X}, size=0x{:X}, permissions=0x{:08X}",
|
||||||
shmem_handle, address, size, map_perm);
|
shmem_handle, address, size, map_perm);
|
||||||
|
|
||||||
// Validate the address/size.
|
// Validate the address/size.
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ namespace Kernel::Svc {
|
|||||||
|
|
||||||
/// Close a handle
|
/// Close a handle
|
||||||
Result CloseHandle(Core::System& system, Handle handle) {
|
Result CloseHandle(Core::System& system, Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "Closing handle {:#08x}", handle);
|
LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
|
||||||
|
|
||||||
// Remove the handle.
|
// Remove the handle.
|
||||||
R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(system.Kernel(), handle),
|
R_UNLESS(GetCurrentProcess(system.Kernel()).GetHandleTable().Remove(system.Kernel(), handle),
|
||||||
@@ -28,7 +28,7 @@ Result CloseHandle(Core::System& system, Handle handle) {
|
|||||||
|
|
||||||
/// Clears the signaled state of an event or process.
|
/// Clears the signaled state of an event or process.
|
||||||
Result ResetSignal(Core::System& system, Handle handle) {
|
Result ResetSignal(Core::System& system, Handle handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called handle {:#08x}", handle);
|
LOG_DEBUG(Kernel_SVC, "called handle 0x{:08X}", handle);
|
||||||
|
|
||||||
// Get the current handle table.
|
// Get the current handle table.
|
||||||
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
const auto& handle_table = GetCurrentProcess(system.Kernel()).GetHandleTable();
|
||||||
@@ -103,7 +103,7 @@ Result WaitSynchronization(Core::System& system, int32_t* out_index, u64 user_ha
|
|||||||
|
|
||||||
/// Resumes a thread waiting on WaitSynchronization
|
/// Resumes a thread waiting on WaitSynchronization
|
||||||
Result CancelSynchronization(Core::System& system, Handle handle) {
|
Result CancelSynchronization(Core::System& system, Handle handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called handle={:#x}", handle);
|
LOG_TRACE(Kernel_SVC, "called handle={:#X}", handle);
|
||||||
|
|
||||||
// Get the thread from its handle.
|
// Get the thread from its handle.
|
||||||
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), handle);
|
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), handle);
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ constexpr bool IsValidVirtualCoreId(int32_t core_id) {
|
|||||||
Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u64 arg,
|
Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u64 arg,
|
||||||
u64 stack_bottom, s32 priority, s32 core_id) {
|
u64 stack_bottom, s32 priority, s32 core_id) {
|
||||||
LOG_DEBUG(Kernel_SVC,
|
LOG_DEBUG(Kernel_SVC,
|
||||||
"called entry_point={:#08x}, arg={:#08x}, stack_bottom={:#08x}, "
|
"called entry_point=0x{:08X}, arg=0x{:08X}, stack_bottom=0x{:08X}, "
|
||||||
"priority={:#08x}, core_id={:#08x}",
|
"priority=0x{:08X}, core_id=0x{:08X}",
|
||||||
entry_point, arg, stack_bottom, priority, core_id);
|
entry_point, arg, stack_bottom, priority, core_id);
|
||||||
|
|
||||||
// Adjust core id, if it's the default magic.
|
// Adjust core id, if it's the default magic.
|
||||||
@@ -85,7 +85,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
|
|||||||
|
|
||||||
/// Starts the thread for the provided handle
|
/// Starts the thread for the provided handle
|
||||||
Result StartThread(Core::System& system, Handle thread_handle) {
|
Result StartThread(Core::System& system, Handle thread_handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called thread={:#08x}", thread_handle);
|
LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
|
||||||
|
|
||||||
// Get the thread from its handle.
|
// Get the thread from its handle.
|
||||||
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle);
|
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle);
|
||||||
@@ -143,7 +143,7 @@ void SleepThread(Core::System& system, s64 ns) {
|
|||||||
|
|
||||||
/// Gets the thread context
|
/// Gets the thread context
|
||||||
Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) {
|
Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_handle) {
|
||||||
LOG_DEBUG(Kernel_SVC, "called, out_context={:#08x}, thread_handle={:#x}", out_context, thread_handle);
|
LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle={:#X}", out_context, thread_handle);
|
||||||
|
|
||||||
// Get the thread from its handle.
|
// Get the thread from its handle.
|
||||||
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle);
|
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle);
|
||||||
@@ -202,7 +202,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
|
|||||||
// TODO: Handle this case when debug events are supported.
|
// TODO: Handle this case when debug events are supported.
|
||||||
UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
|
UNIMPLEMENTED_IF(debug_handle != InvalidHandle);
|
||||||
|
|
||||||
LOG_DEBUG(Kernel_SVC, "called. out_thread_ids={:#016x}, out_thread_ids_size={}",
|
LOG_DEBUG(Kernel_SVC, "called. out_thread_ids=0x{:016X}, out_thread_ids_size={}",
|
||||||
out_thread_ids, out_thread_ids_size);
|
out_thread_ids, out_thread_ids_size);
|
||||||
|
|
||||||
// If the size is negative or larger than INT32_MAX / sizeof(u64)
|
// If the size is negative or larger than INT32_MAX / sizeof(u64)
|
||||||
@@ -217,7 +217,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
|
|||||||
|
|
||||||
if (out_thread_ids_size > 0 &&
|
if (out_thread_ids_size > 0 &&
|
||||||
!current_process->GetPageTable().Contains(out_thread_ids, total_copy_size)) {
|
!current_process->GetPageTable().Contains(out_thread_ids, total_copy_size)) {
|
||||||
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin={:#016x}, end={:#016x}",
|
LOG_ERROR(Kernel_SVC, "Address range outside address space. begin=0x{:016X}, end=0x{:016X}",
|
||||||
out_thread_ids, out_thread_ids + total_copy_size);
|
out_thread_ids, out_thread_ids + total_copy_size);
|
||||||
R_THROW(ResultInvalidCurrentMemory);
|
R_THROW(ResultInvalidCurrentMemory);
|
||||||
}
|
}
|
||||||
@@ -239,7 +239,7 @@ Result GetThreadList(Core::System& system, s32* out_num_threads, u64 out_thread_
|
|||||||
|
|
||||||
Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affinity_mask,
|
Result GetThreadCoreMask(Core::System& system, s32* out_core_id, u64* out_affinity_mask,
|
||||||
Handle thread_handle) {
|
Handle thread_handle) {
|
||||||
LOG_TRACE(Kernel_SVC, "called, handle={:#08x}", thread_handle);
|
LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
|
||||||
|
|
||||||
// Get the thread from its handle.
|
// Get the thread from its handle.
|
||||||
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle);
|
KScopedAutoObject thread = GetCurrentProcess(system.Kernel()).GetHandleTable().GetObject<KThread>(system.Kernel(), thread_handle);
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) {
|
|||||||
Core::HID::ControllerUpdateCallback engine_callback{
|
Core::HID::ControllerUpdateCallback engine_callback{
|
||||||
.on_change = [this, &window_system](Core::HID::ControllerTriggerType type) {
|
.on_change = [this, &window_system](Core::HID::ControllerTriggerType type) {
|
||||||
if (type == Core::HID::ControllerTriggerType::Button) {
|
if (type == Core::HID::ControllerTriggerType::Button) {
|
||||||
|
std::unique_lock lk{m_mutex};
|
||||||
OnButtonStateChanged(window_system);
|
OnButtonStateChanged(window_system);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -51,11 +52,29 @@ ButtonPoller::ButtonPoller(Core::System& system, WindowSystem& window_system) {
|
|||||||
m_handheld_key = m_handheld->SetCallback(engine_callback);
|
m_handheld_key = m_handheld->SetCallback(engine_callback);
|
||||||
m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
|
m_player1 = system.HIDCore().GetEmulatedController(Core::HID::NpadIdType::Player1);
|
||||||
m_player1_key = m_player1->SetCallback(engine_callback);
|
m_player1_key = m_player1->SetCallback(engine_callback);
|
||||||
|
|
||||||
|
m_thread = std::jthread([this, &window_system](std::stop_token stop_token) {
|
||||||
|
Common::SetCurrentThreadName("ButtonPoller");
|
||||||
|
while (!stop_token.stop_requested()) {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
std::unique_lock lk{m_mutex};
|
||||||
|
m_cv.wait_for(lk, 50ms);
|
||||||
|
if (stop_token.stop_requested())
|
||||||
|
break;
|
||||||
|
OnButtonStateChanged(window_system);
|
||||||
|
std::this_thread::sleep_for(5ms);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
ButtonPoller::~ButtonPoller() {
|
ButtonPoller::~ButtonPoller() {
|
||||||
m_handheld->DeleteCallback(m_handheld_key);
|
m_handheld->DeleteCallback(m_handheld_key);
|
||||||
m_player1->DeleteCallback(m_player1_key);
|
m_player1->DeleteCallback(m_player1_key);
|
||||||
|
m_cv.notify_all();
|
||||||
|
if (m_thread.joinable()) {
|
||||||
|
m_thread.request_stop();
|
||||||
|
m_thread.join();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) {
|
void ButtonPoller::OnButtonStateChanged(WindowSystem& window_system) {
|
||||||
|
|||||||
@@ -33,6 +33,9 @@ public:
|
|||||||
void OnButtonStateChanged(WindowSystem& window_system);
|
void OnButtonStateChanged(WindowSystem& window_system);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::mutex m_mutex;
|
||||||
|
std::condition_variable m_cv;
|
||||||
|
std::jthread m_thread;
|
||||||
std::optional<std::chrono::steady_clock::time_point> m_home_button_press_start{};
|
std::optional<std::chrono::steady_clock::time_point> m_home_button_press_start{};
|
||||||
std::optional<std::chrono::steady_clock::time_point> m_capture_button_press_start{};
|
std::optional<std::chrono::steady_clock::time_point> m_capture_button_press_start{};
|
||||||
std::optional<std::chrono::steady_clock::time_point> m_power_button_press_start{};
|
std::optional<std::chrono::steady_clock::time_point> m_power_button_press_start{};
|
||||||
|
|||||||
@@ -26,12 +26,13 @@ EventObserver::EventObserver(Core::System& system, WindowSystem& window_system)
|
|||||||
m_window_system.SetEventObserver(this);
|
m_window_system.SetEventObserver(this);
|
||||||
m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent));
|
m_wakeup_holder.SetUserData(static_cast<uintptr_t>(UserDataTag::WakeupEvent));
|
||||||
m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait));
|
m_wakeup_holder.LinkToMultiWait(std::addressof(m_multi_wait));
|
||||||
m_thread = std::jthread([this](std::stop_token stop_token) {
|
m_thread = std::thread([this] {
|
||||||
Common::SetCurrentThreadName("am:EventObserver");
|
Common::SetCurrentThreadName("am:EventObserver");
|
||||||
while (!stop_token.stop_requested()) {
|
while (true) {
|
||||||
auto* signaled_holder = this->WaitSignaled(stop_token);
|
auto* signaled_holder = this->WaitSignaled();
|
||||||
if (!signaled_holder)
|
if (!signaled_holder) {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
this->Process(signaled_holder);
|
this->Process(signaled_holder);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -39,12 +40,9 @@ EventObserver::EventObserver(Core::System& system, WindowSystem& window_system)
|
|||||||
|
|
||||||
EventObserver::~EventObserver() {
|
EventObserver::~EventObserver() {
|
||||||
// Signal thread and wait for processing to finish.
|
// Signal thread and wait for processing to finish.
|
||||||
if (m_thread.joinable()) {
|
m_stop_source.request_stop();
|
||||||
// Signal thread and wait for processing to finish.
|
m_wakeup_event.Signal(m_system.Kernel());
|
||||||
m_thread.request_stop();
|
m_thread.join();
|
||||||
m_wakeup_event.Signal(m_system.Kernel());
|
|
||||||
m_thread.join();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Free remaining owned sessions.
|
// Free remaining owned sessions.
|
||||||
auto it = m_process_holder_list.begin();
|
auto it = m_process_holder_list.begin();
|
||||||
@@ -90,12 +88,12 @@ void EventObserver::LinkDeferred() {
|
|||||||
m_multi_wait.MoveAll(std::addressof(m_deferred_wait_list));
|
m_multi_wait.MoveAll(std::addressof(m_deferred_wait_list));
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiWaitHolder* EventObserver::WaitSignaled(std::stop_token stop_token) {
|
MultiWaitHolder* EventObserver::WaitSignaled() {
|
||||||
while (true) {
|
while (true) {
|
||||||
this->LinkDeferred();
|
this->LinkDeferred();
|
||||||
|
|
||||||
// If we're done, return before we start waiting.
|
// If we're done, return before we start waiting.
|
||||||
if (stop_token.stop_requested()) {
|
if (m_stop_source.stop_requested()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +131,7 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) {
|
|||||||
// Check process state.
|
// Check process state.
|
||||||
auto& applet = holder->GetApplet();
|
auto& applet = holder->GetApplet();
|
||||||
auto& process = holder->GetProcess();
|
auto& process = holder->GetProcess();
|
||||||
|
|
||||||
{
|
{
|
||||||
std::scoped_lock lk{m_lock, applet.lock};
|
std::scoped_lock lk{m_lock, applet.lock};
|
||||||
if (process.IsTerminated()) {
|
if (process.IsTerminated()) {
|
||||||
@@ -157,6 +156,7 @@ void EventObserver::OnProcessEvent(ProcessHolder* holder) {
|
|||||||
void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) {
|
void EventObserver::DestroyAppletProcessHolderLocked(ProcessHolder* holder) {
|
||||||
// Remove from owned list.
|
// Remove from owned list.
|
||||||
m_process_holder_list.erase(m_process_holder_list.iterator_to(*holder));
|
m_process_holder_list.erase(m_process_holder_list.iterator_to(*holder));
|
||||||
|
|
||||||
// Destroy and free.
|
// Destroy and free.
|
||||||
delete holder;
|
delete holder;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,14 +32,19 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void LinkDeferred();
|
void LinkDeferred();
|
||||||
MultiWaitHolder* WaitSignaled(std::stop_token stop_token);
|
MultiWaitHolder* WaitSignaled();
|
||||||
void Process(MultiWaitHolder* holder);
|
void Process(MultiWaitHolder* holder);
|
||||||
bool WaitAndProcessImpl();
|
bool WaitAndProcessImpl();
|
||||||
void LoopProcess();
|
void LoopProcess();
|
||||||
|
|
||||||
|
private:
|
||||||
void OnWakeupEvent(MultiWaitHolder* holder);
|
void OnWakeupEvent(MultiWaitHolder* holder);
|
||||||
void OnProcessEvent(ProcessHolder* holder);
|
void OnProcessEvent(ProcessHolder* holder);
|
||||||
|
|
||||||
|
private:
|
||||||
void DestroyAppletProcessHolderLocked(ProcessHolder* holder);
|
void DestroyAppletProcessHolderLocked(ProcessHolder* holder);
|
||||||
|
|
||||||
|
private:
|
||||||
// System reference and context.
|
// System reference and context.
|
||||||
Core::System& m_system;
|
Core::System& m_system;
|
||||||
KernelHelpers::ServiceContext m_context;
|
KernelHelpers::ServiceContext m_context;
|
||||||
@@ -62,7 +67,8 @@ private:
|
|||||||
MultiWait m_deferred_wait_list;
|
MultiWait m_deferred_wait_list;
|
||||||
|
|
||||||
// Processing thread.
|
// Processing thread.
|
||||||
std::jthread m_thread{};
|
std::thread m_thread{};
|
||||||
|
std::stop_source m_stop_source{};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::AM
|
} // namespace Service::AM
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
#include <openssl/evp.h>
|
|
||||||
|
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "common/uuid.h"
|
#include "common/uuid.h"
|
||||||
#include "core/file_sys/control_metadata.h"
|
#include "core/file_sys/control_metadata.h"
|
||||||
@@ -156,7 +154,20 @@ Result IApplicationFunctions::GetDesiredLanguage(Out<u64> out_language_code) {
|
|||||||
// Default to 0 (all languages supported)
|
// Default to 0 (all languages supported)
|
||||||
u32 supported_languages = 0;
|
u32 supported_languages = 0;
|
||||||
|
|
||||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
|
const auto res = [this] {
|
||||||
|
const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
if (res.first != nullptr) {
|
if (res.first != nullptr) {
|
||||||
supported_languages = res.first->GetSupportedLanguages();
|
supported_languages = res.first->GetSupportedLanguages();
|
||||||
}
|
}
|
||||||
@@ -194,7 +205,20 @@ Result IApplicationFunctions::SetTerminateResult(Result terminate_result) {
|
|||||||
Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
|
Result IApplicationFunctions::GetDisplayVersion(Out<DisplayVersion> out_display_version) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
|
const auto res = [this] {
|
||||||
|
const FileSys::PatchManager pm{m_applet->program_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(m_applet->program_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
if (res.first != nullptr) {
|
if (res.first != nullptr) {
|
||||||
const auto& version = res.first->GetVersionString();
|
const auto& version = res.first->GetVersionString();
|
||||||
std::memcpy(out_display_version->string.data(), version.data(),
|
std::memcpy(out_display_version->string.data(), version.data(),
|
||||||
@@ -323,21 +347,8 @@ Result IApplicationFunctions::NotifyRunning(Out<bool> out_became_running) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
|
Result IApplicationFunctions::GetPseudoDeviceId(Out<Common::UUID> out_pseudo_device_id) {
|
||||||
LOG_WARNING(Service_AM, "(stubbed)");
|
LOG_WARNING(Service_AM, "(STUBBED) called");
|
||||||
|
*out_pseudo_device_id = {};
|
||||||
// This should be hashed with the device specific hash
|
|
||||||
// for now this will do
|
|
||||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, m_applet->program_id);
|
|
||||||
u8 hash[EVP_MAX_MD_SIZE];
|
|
||||||
unsigned int hash_len = 0;
|
|
||||||
auto const seed = res.first->raw.seed_for_pseudo_device_id;
|
|
||||||
EVP_MD_CTX *ctx = EVP_MD_CTX_new();
|
|
||||||
auto const algorithm = EVP_sha1();
|
|
||||||
EVP_DigestInit_ex(ctx, algorithm, nullptr);
|
|
||||||
EVP_DigestUpdate(ctx, &seed, sizeof(seed));
|
|
||||||
EVP_DigestFinal_ex(ctx, hash, &hash_len);
|
|
||||||
EVP_MD_CTX_free(ctx);
|
|
||||||
*out_pseudo_device_id = Common::UUID::MakeRFC4122V5(std::span<u8, 20>{hash, std::size(hash)});
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -252,7 +252,19 @@ Result ILibraryAppletSelfAccessor::GetMainAppletApplicationDesiredLanguage(
|
|||||||
// Default to 0 (all languages supported)
|
// Default to 0 (all languages supported)
|
||||||
u32 supported_languages = 0;
|
u32 supported_languages = 0;
|
||||||
|
|
||||||
const auto res = FileSys::PatchManager::GetMetadataFromBaseOrUpdate(system, identity.application_id);
|
const auto res = [this, identity] {
|
||||||
|
const FileSys::PatchManager pm{identity.application_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
auto metadata = pm.GetControlMetadata();
|
||||||
|
if (metadata.first != nullptr) {
|
||||||
|
return metadata;
|
||||||
|
}
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm_update{FileSys::GetUpdateTitleID(identity.application_id),
|
||||||
|
system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
return pm_update.GetControlMetadata();
|
||||||
|
}();
|
||||||
|
|
||||||
if (res.first != nullptr) {
|
if (res.first != nullptr) {
|
||||||
supported_languages = res.first->GetSupportedLanguages();
|
supported_languages = res.first->GetSupportedLanguages();
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ Result IAudioRenderer::RequestUpdateAuto(
|
|||||||
|
|
||||||
const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
|
const auto result = impl->RequestUpdate(input, out_performance_buffer, out_buffer);
|
||||||
if (result.IsFailure()) {
|
if (result.IsFailure()) {
|
||||||
LOG_ERROR(Service_Audio, "RequestUpdate failed error {:#02x}!", result.GetDescription());
|
LOG_ERROR(Service_Audio, "RequestUpdate failed error 0x{:02X}!", result.GetDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
R_RETURN(result);
|
R_RETURN(result);
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ Result IAlbumAccessorService::GetAlbumFileList(
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) {
|
Result IAlbumAccessorService::DeleteAlbumFile(AlbumFileId file_id) {
|
||||||
LOG_INFO(Service_Capture, "called, application_id={:#0x}, storage={}, type={}",
|
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}",
|
||||||
file_id.application_id, file_id.storage, file_id.type);
|
file_id.application_id, file_id.storage, file_id.type);
|
||||||
|
|
||||||
const Result result = manager->DeleteAlbumFile(file_id);
|
const Result result = manager->DeleteAlbumFile(file_id);
|
||||||
@@ -120,7 +120,7 @@ Result IAlbumAccessorService::LoadAlbumScreenShotImageEx1(
|
|||||||
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
||||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
||||||
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer) {
|
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer) {
|
||||||
LOG_INFO(Service_Capture, "called, application_id={:#0x}, storage={}, type={}, flags={}",
|
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
|
||||||
file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
|
file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
|
||||||
|
|
||||||
const Result result =
|
const Result result =
|
||||||
@@ -133,7 +133,7 @@ Result IAlbumAccessorService::LoadAlbumScreenShotThumbnailImageEx1(
|
|||||||
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
OutLargeData<LoadAlbumScreenShotImageOutput, BufferAttr_HipcMapAlias> out_image_output,
|
||||||
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
OutArray<u8, BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_image,
|
||||||
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer) {
|
OutArray<u8, BufferAttr_HipcMapAlias> out_buffer) {
|
||||||
LOG_INFO(Service_Capture, "called, application_id={:#0x}, storage={}, type={}, flags={}",
|
LOG_INFO(Service_Capture, "called, application_id=0x{:0x}, storage={}, type={}, flags={}",
|
||||||
file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
|
file_id.application_id, file_id.storage, file_id.type, decoder_options.flags);
|
||||||
|
|
||||||
const Result result = manager->LoadAlbumScreenShotThumbnail(*out_image_output, out_image,
|
const Result result = manager->LoadAlbumScreenShotThumbnail(*out_image_output, out_image,
|
||||||
|
|||||||
@@ -444,7 +444,7 @@ void CmifReplyWrapImpl(HLERequestContext& ctx, T& t, Result (T::*f)(A...)) {
|
|||||||
const bool is_domain = mgr ? mgr->IsDomain() : false;
|
const bool is_domain = mgr ? mgr->IsDomain() : false;
|
||||||
ASSERT_MSG(!is_domain,
|
ASSERT_MSG(!is_domain,
|
||||||
"Non-domain reply used on domain session\n"
|
"Non-domain reply used on domain session\n"
|
||||||
"Service={} (TIPC={} CmdType={} Cmd={:#08x}\n"
|
"Service={} (TIPC={} CmdType={} Cmd=0x{:08X}\n"
|
||||||
"HasDomainHeader={} DomainHandlers={}\nDesc={}",
|
"HasDomainHeader={} DomainHandlers={}\nDesc={}",
|
||||||
t.GetServiceName(), ctx.IsTipc(),
|
t.GetServiceName(), ctx.IsTipc(),
|
||||||
u32(ctx.GetCommandType()), u32(ctx.GetCommand()),
|
u32(ctx.GetCommandType()), u32(ctx.GetCommand()),
|
||||||
|
|||||||
@@ -71,9 +71,9 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F
|
|||||||
std::string crash_report = fmt::format(
|
std::string crash_report = fmt::format(
|
||||||
"Eden {}-{} crash report\n"
|
"Eden {}-{} crash report\n"
|
||||||
"Title ID: {:016x}\n"
|
"Title ID: {:016x}\n"
|
||||||
"Result: {:#x} ({:04}-{:04d})\n"
|
"Result: {:#X} ({:04}-{:04d})\n"
|
||||||
"Set flags: {:#16X}\n"
|
"Set flags: 0x{:16X}\n"
|
||||||
"Program entry point: {:#16X}\n"
|
"Program entry point: 0x{:16X}\n"
|
||||||
"\n",
|
"\n",
|
||||||
Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw,
|
Common::g_scm_branch, Common::g_scm_desc, title_id, error_code.raw,
|
||||||
2000 + static_cast<u32>(error_code.GetModule()),
|
2000 + static_cast<u32>(error_code.GetModule()),
|
||||||
@@ -98,7 +98,7 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F
|
|||||||
}
|
}
|
||||||
|
|
||||||
crash_report += fmt::format("Architecture: {}\n", info.ArchAsString());
|
crash_report += fmt::format("Architecture: {}\n", info.ArchAsString());
|
||||||
crash_report += fmt::format("Unknown 10: {:#016x}\n", info.unk10);
|
crash_report += fmt::format("Unknown 10: 0x{:016x}\n", info.unk10);
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG_ERROR(Service_Fatal, "{}", crash_report);
|
LOG_ERROR(Service_Fatal, "{}", crash_report);
|
||||||
@@ -111,7 +111,7 @@ static void GenerateErrorReport(Core::System& system, Result error_code, const F
|
|||||||
|
|
||||||
static void ThrowFatalError(Core::System& system, Result error_code, FatalType fatal_type,
|
static void ThrowFatalError(Core::System& system, Result error_code, FatalType fatal_type,
|
||||||
const FatalInfo& info) {
|
const FatalInfo& info) {
|
||||||
LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code {:#x}", fatal_type,
|
LOG_ERROR(Service_Fatal, "Threw fatal error type {} with error code {:#X}", fatal_type,
|
||||||
error_code.raw);
|
error_code.raw);
|
||||||
|
|
||||||
switch (fatal_type) {
|
switch (fatal_type) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -30,7 +30,7 @@ Result IFile::Read(
|
|||||||
FileSys::ReadOption option, Out<s64> out_size, s64 offset,
|
FileSys::ReadOption option, Out<s64> out_size, s64 offset,
|
||||||
const OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_buffer,
|
const OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_buffer,
|
||||||
s64 size) {
|
s64 size) {
|
||||||
LOG_DEBUG(Service_FS, "called, option={}, offset={:#x}, length={}", option.value, offset,
|
LOG_DEBUG(Service_FS, "called, option={}, offset={:#X}, length={}", option.value, offset,
|
||||||
size);
|
size);
|
||||||
|
|
||||||
// Read the data from the Storage backend
|
// Read the data from the Storage backend
|
||||||
@@ -41,7 +41,7 @@ Result IFile::Read(
|
|||||||
Result IFile::Write(
|
Result IFile::Write(
|
||||||
const InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> buffer,
|
const InBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> buffer,
|
||||||
FileSys::WriteOption option, s64 offset, s64 size) {
|
FileSys::WriteOption option, s64 offset, s64 size) {
|
||||||
LOG_DEBUG(Service_FS, "called, option={}, offset={:#x}, length={}", option.value, offset,
|
LOG_DEBUG(Service_FS, "called, option={}, offset={:#X}, length={}", option.value, offset,
|
||||||
size);
|
size);
|
||||||
|
|
||||||
R_RETURN(backend->Write(offset, buffer.data(), size, option));
|
R_RETURN(backend->Write(offset, buffer.data(), size, option));
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ IFileSystem::IFileSystem(Core::System& system_, FileSys::VirtualDir dir_, SizeGe
|
|||||||
|
|
||||||
Result IFileSystem::CreateFile(const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path,
|
Result IFileSystem::CreateFile(const InLargeData<FileSys::Sf::Path, BufferAttr_HipcPointer> path,
|
||||||
s32 option, s64 size) {
|
s32 option, s64 size) {
|
||||||
LOG_DEBUG(Service_FS, "called. file={}, option={:#x}, size={:#08x}", path->str, option, size);
|
LOG_DEBUG(Service_FS, "called. file={}, option={:#X}, size=0x{:08X}", path->str, option, size);
|
||||||
|
|
||||||
R_RETURN(backend->CreateFile(FileSys::Path(path->str), size));
|
R_RETURN(backend->CreateFile(FileSys::Path(path->str), size));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
|
||||||
@@ -26,7 +26,7 @@ IStorage::IStorage(Core::System& system_, FileSys::VirtualFile backend_)
|
|||||||
Result IStorage::Read(
|
Result IStorage::Read(
|
||||||
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_bytes,
|
OutBuffer<BufferAttr_HipcMapAlias | BufferAttr_HipcMapTransferAllowsNonSecure> out_bytes,
|
||||||
s64 offset, s64 length) {
|
s64 offset, s64 length) {
|
||||||
LOG_DEBUG(Service_FS, "called, offset={:#x}, length={}", offset, length);
|
LOG_DEBUG(Service_FS, "called, offset={:#X}, length={}", offset, length);
|
||||||
|
|
||||||
R_UNLESS(length >= 0, FileSys::ResultInvalidSize);
|
R_UNLESS(length >= 0, FileSys::ResultInvalidSize);
|
||||||
R_UNLESS(offset >= 0, FileSys::ResultInvalidOffset);
|
R_UNLESS(offset >= 0, FileSys::ResultInvalidOffset);
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ FSP_SRV::~FSP_SRV() = default;
|
|||||||
Result FSP_SRV::SetCurrentProcess(ClientProcessId pid) {
|
Result FSP_SRV::SetCurrentProcess(ClientProcessId pid) {
|
||||||
current_process_id = *pid;
|
current_process_id = *pid;
|
||||||
|
|
||||||
LOG_DEBUG(Service_FS, "called. current_process_id={:#016x}", current_process_id);
|
LOG_DEBUG(Service_FS, "called. current_process_id=0x{:016X}", current_process_id);
|
||||||
|
|
||||||
R_RETURN(
|
R_RETURN(
|
||||||
fsc.OpenProcess(&program_id, &save_data_controller, &romfs_controller, current_process_id));
|
fsc.OpenProcess(&program_id, &save_data_controller, &romfs_controller, current_process_id));
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ Result IAppletResource::GetSharedMemoryHandle(
|
|||||||
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_handle) {
|
OutCopyHandle<Kernel::KSharedMemory> out_shared_memory_handle) {
|
||||||
const auto result = resource_manager->GetSharedMemoryHandle(out_shared_memory_handle, aruid);
|
const auto result = resource_manager->GetSharedMemoryHandle(out_shared_memory_handle, aruid);
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result={:#x}", aruid, result.raw);
|
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result={:#X}", aruid, result.raw);
|
||||||
R_RETURN(result);
|
R_RETURN(result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -251,7 +251,7 @@ Result IHidServer::CreateAppletResource(OutInterface<IAppletResource> out_applet
|
|||||||
ClientAppletResourceUserId aruid) {
|
ClientAppletResourceUserId aruid) {
|
||||||
const auto result = GetResourceManager()->CreateAppletResource(aruid.pid);
|
const auto result = GetResourceManager()->CreateAppletResource(aruid.pid);
|
||||||
|
|
||||||
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result={:#x}", aruid.pid,
|
LOG_DEBUG(Service_HID, "called, applet_resource_user_id={}, result={:#X}", aruid.pid,
|
||||||
result.raw);
|
result.raw);
|
||||||
|
|
||||||
*out_applet_resource = std::make_shared<IAppletResource>(system, resource_manager, aruid.pid);
|
*out_applet_resource = std::make_shared<IAppletResource>(system, resource_manager, aruid.pid);
|
||||||
@@ -1150,7 +1150,7 @@ Result IHidServer::InitializeSevenSixAxisSensor(ClientAppletResourceUserId aruid
|
|||||||
InCopyHandle<Kernel::KTransferMemory> t_mem_1,
|
InCopyHandle<Kernel::KTransferMemory> t_mem_1,
|
||||||
InCopyHandle<Kernel::KTransferMemory> t_mem_2) {
|
InCopyHandle<Kernel::KTransferMemory> t_mem_2) {
|
||||||
LOG_WARNING(Service_HID,
|
LOG_WARNING(Service_HID,
|
||||||
"called, t_mem_1_size={:#08x}, t_mem_2_size={:#08x}, "
|
"called, t_mem_1_size=0x{:08X}, t_mem_2_size=0x{:08X}, "
|
||||||
"applet_resource_user_id={}",
|
"applet_resource_user_id={}",
|
||||||
t_mem_1_size, t_mem_2_size, aruid.pid);
|
t_mem_1_size, t_mem_2_size, aruid.pid);
|
||||||
|
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ Result SessionRequestManager::HandleDomainSyncRequest(Kernel::KServerSession* se
|
|||||||
}
|
}
|
||||||
|
|
||||||
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
|
case IPC::DomainMessageHeader::CommandType::CloseVirtualHandle: {
|
||||||
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id={:#08x}", object_id);
|
LOG_DEBUG(IPC, "CloseVirtualHandle, object_id=0x{:08X}", object_id);
|
||||||
|
|
||||||
this->CloseDomainHandler(object_id - 1);
|
this->CloseDomainHandler(object_id - 1);
|
||||||
|
|
||||||
|
|||||||
@@ -142,7 +142,7 @@ public:
|
|||||||
if (boost::icl::contains(mapped_ranges, vaddr)) {
|
if (boost::icl::contains(mapped_ranges, vaddr)) {
|
||||||
memory.ReadBlock(vaddr, &ret, sizeof(T));
|
memory.ReadBlock(vaddr, &ret, sizeof(T));
|
||||||
} else if (vaddr + sizeof(T) > local_memory.size()) {
|
} else if (vaddr + sizeof(T) > local_memory.size()) {
|
||||||
LOG_CRITICAL(Service_JIT, "plugin: unmapped read @ {:#016x}", vaddr);
|
LOG_CRITICAL(Service_JIT, "plugin: unmapped read @ 0x{:016x}", vaddr);
|
||||||
} else {
|
} else {
|
||||||
std::memcpy(&ret, local_memory.data() + vaddr, sizeof(T));
|
std::memcpy(&ret, local_memory.data() + vaddr, sizeof(T));
|
||||||
}
|
}
|
||||||
@@ -154,7 +154,7 @@ public:
|
|||||||
if (boost::icl::contains(mapped_ranges, vaddr)) {
|
if (boost::icl::contains(mapped_ranges, vaddr)) {
|
||||||
memory.WriteBlock(vaddr, &value, sizeof(T));
|
memory.WriteBlock(vaddr, &value, sizeof(T));
|
||||||
} else if (vaddr + sizeof(T) > local_memory.size()) {
|
} else if (vaddr + sizeof(T) > local_memory.size()) {
|
||||||
LOG_CRITICAL(Service_JIT, "plugin: unmapped write @ {:#016x}", vaddr);
|
LOG_CRITICAL(Service_JIT, "plugin: unmapped write @ 0x{:016x}", vaddr);
|
||||||
} else {
|
} else {
|
||||||
std::memcpy(local_memory.data() + vaddr, &value, sizeof(T));
|
std::memcpy(local_memory.data() + vaddr, &value, sizeof(T));
|
||||||
}
|
}
|
||||||
@@ -416,7 +416,7 @@ void DynarmicCallbacks64::CallSVC(u32 swi) {
|
|||||||
LOG_CRITICAL(Service_JIT, "plugin panicked!");
|
LOG_CRITICAL(Service_JIT, "plugin panicked!");
|
||||||
parent.jit->HaltExecution();
|
parent.jit->HaltExecution();
|
||||||
} else {
|
} else {
|
||||||
LOG_CRITICAL(Service_JIT, "plugin issued syscall at unknown address {:#x}", pc);
|
LOG_CRITICAL(Service_JIT, "plugin issued syscall at unknown address 0x{:x}", pc);
|
||||||
parent.jit->HaltExecution();
|
parent.jit->HaltExecution();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ Result DatabaseManager::Initialize(DatabaseSessionMetadata& metadata, bool& is_d
|
|||||||
const auto result = database.CheckIntegrity();
|
const auto result = database.CheckIntegrity();
|
||||||
|
|
||||||
if (result.IsError()) {
|
if (result.IsError()) {
|
||||||
LOG_ERROR(Service_Mii, "Mii database is corrupted {:#0x}", result.raw);
|
LOG_ERROR(Service_Mii, "Mii database is corrupted 0x{:0x}", result.raw);
|
||||||
database.CleanDatabase();
|
database.CleanDatabase();
|
||||||
return ResultSuccess;
|
return ResultSuccess;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ void nvhost_as_gpu::OnOpen(NvCore::SessionId session_id, DeviceFD fd) {}
|
|||||||
void nvhost_as_gpu::OnClose(DeviceFD fd) {}
|
void nvhost_as_gpu::OnClose(DeviceFD fd) {}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, big_page_size={:#x}", params.big_page_size);
|
LOG_DEBUG(Service_NVDRV, "called, big_page_size={:#X}", params.big_page_size);
|
||||||
|
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
|
|
||||||
@@ -105,12 +105,12 @@ NvResult nvhost_as_gpu::AllocAsEx(IoctlAllocAsEx& params) {
|
|||||||
|
|
||||||
if (params.big_page_size) {
|
if (params.big_page_size) {
|
||||||
if (!std::has_single_bit(params.big_page_size)) {
|
if (!std::has_single_bit(params.big_page_size)) {
|
||||||
LOG_ERROR(Service_NVDRV, "Non power-of-2 big page size: {:#x}!", params.big_page_size);
|
LOG_ERROR(Service_NVDRV, "Non power-of-2 big page size: {:#X}!", params.big_page_size);
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((params.big_page_size & VM::SUPPORTED_BIG_PAGE_SIZES) == 0) {
|
if ((params.big_page_size & VM::SUPPORTED_BIG_PAGE_SIZES) == 0) {
|
||||||
LOG_ERROR(Service_NVDRV, "Unsupported big page size: {:#x}!", params.big_page_size);
|
LOG_ERROR(Service_NVDRV, "Unsupported big page size: {:#X}!", params.big_page_size);
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,7 +252,7 @@ NvResult nvhost_as_gpu::FreeSpace(IoctlFreeSpace& params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
|
NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, num_entries={:#x}", entries.size());
|
LOG_DEBUG(Service_NVDRV, "called, num_entries={:#X}", entries.size());
|
||||||
|
|
||||||
if (!vm.initialised) {
|
if (!vm.initialised) {
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
@@ -300,7 +300,7 @@ NvResult nvhost_as_gpu::Remap(std::span<IoctlRemapEntry> entries) {
|
|||||||
NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
|
NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
|
||||||
LOG_DEBUG(Service_NVDRV,
|
LOG_DEBUG(Service_NVDRV,
|
||||||
"called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
|
"called, flags={:X}, nvmap_handle={:X}, buffer_offset={}, mapping_size={}"
|
||||||
", offset={:#x}",
|
", offset={:#X}",
|
||||||
params.flags, params.handle, params.buffer_offset, params.mapping_size,
|
params.flags, params.handle, params.buffer_offset, params.mapping_size,
|
||||||
params.offset);
|
params.offset);
|
||||||
|
|
||||||
@@ -315,7 +315,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
|
|||||||
if (auto const it = mapping_map.find(params.offset); it != mapping_map.end()) {
|
if (auto const it = mapping_map.find(params.offset); it != mapping_map.end()) {
|
||||||
auto const mapping = it->second;
|
auto const mapping = it->second;
|
||||||
if (mapping.size < params.mapping_size) {
|
if (mapping.size < params.mapping_size) {
|
||||||
LOG_WARNING(Service_NVDRV, "Cannot remap a partially mapped GPU address space region: {:#x}", params.offset);
|
LOG_WARNING(Service_NVDRV, "Cannot remap a partially mapped GPU address space region: {:#X}", params.offset);
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
u64 gpu_address = u64(params.offset + params.buffer_offset);
|
u64 gpu_address = u64(params.offset + params.buffer_offset);
|
||||||
@@ -323,7 +323,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
|
|||||||
gmmu->Map(gpu_address, device_address, params.mapping_size, Tegra::PTEKind(params.kind), mapping.big_page);
|
gmmu->Map(gpu_address, device_address, params.mapping_size, Tegra::PTEKind(params.kind), mapping.big_page);
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
} else {
|
} else {
|
||||||
LOG_WARNING(Service_NVDRV, "Cannot remap an unmapped GPU address space region: {:#x}", params.offset);
|
LOG_WARNING(Service_NVDRV, "Cannot remap an unmapped GPU address space region: {:#X}", params.offset);
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -383,7 +383,7 @@ NvResult nvhost_as_gpu::MapBufferEx(IoctlMapBufferEx& params) {
|
|||||||
NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
|
NvResult nvhost_as_gpu::UnmapBuffer(IoctlUnmapBuffer& params) {
|
||||||
std::scoped_lock lock(mutex);
|
std::scoped_lock lock(mutex);
|
||||||
if (auto const offset_it = map_buffer_offsets.find(params.offset); offset_it != map_buffer_offsets.end()) {
|
if (auto const offset_it = map_buffer_offsets.find(params.offset); offset_it != map_buffer_offsets.end()) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, offset={:#x}", params.offset);
|
LOG_DEBUG(Service_NVDRV, "called, offset={:#X}", params.offset);
|
||||||
if (!vm.initialised) {
|
if (!vm.initialised) {
|
||||||
return NvResult::BadValue;
|
return NvResult::BadValue;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -210,7 +210,7 @@ NvResult nvhost_ctrl_gpu::GetCharacteristics3(
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) {
|
NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size={:#x}", params.mask_buffer_size);
|
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size={:#X}", params.mask_buffer_size);
|
||||||
if (params.mask_buffer_size != 0) {
|
if (params.mask_buffer_size != 0) {
|
||||||
params.tcp_mask = 3;
|
params.tcp_mask = 3;
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ NvResult nvhost_ctrl_gpu::GetTPCMasks1(IoctlGpuGetTpcMasksArgs& params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) {
|
NvResult nvhost_ctrl_gpu::GetTPCMasks3(IoctlGpuGetTpcMasksArgs& params, std::span<u32> tpc_mask) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size={:#x}", params.mask_buffer_size);
|
LOG_DEBUG(Service_NVDRV, "called, mask_buffer_size={:#X}", params.mask_buffer_size);
|
||||||
if (params.mask_buffer_size != 0) {
|
if (params.mask_buffer_size != 0) {
|
||||||
params.tcp_mask = 3;
|
params.tcp_mask = 3;
|
||||||
}
|
}
|
||||||
@@ -265,7 +265,7 @@ NvResult nvhost_ctrl_gpu::ZCullGetInfo(IoctlNvgpuGpuZcullGetInfoArgs& params) {
|
|||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
|
NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
|
||||||
if (params.type > supported_types) {
|
if (params.type > supported_types) {
|
||||||
LOG_ERROR(Service_NVDRV, "ZBCSetTable: invalid type {:#x}", params.type);
|
LOG_ERROR(Service_NVDRV, "ZBCSetTable: invalid type {:#X}", params.type);
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,11 +288,11 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
|
|||||||
|
|
||||||
if (color_it != zbc_colors.end()) {
|
if (color_it != zbc_colors.end()) {
|
||||||
++color_it->ref_cnt;
|
++color_it->ref_cnt;
|
||||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused color entry fmt={:#x}, ref_cnt={:#x}",
|
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused color entry fmt={:#X}, ref_cnt={:#X}",
|
||||||
params.format, color_it->ref_cnt);
|
params.format, color_it->ref_cnt);
|
||||||
} else {
|
} else {
|
||||||
zbc_colors.push_back(color_entry);
|
zbc_colors.push_back(color_entry);
|
||||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added color entry fmt={:#x}, index={:#x}",
|
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added color entry fmt={:#X}, index={:#X}",
|
||||||
params.format, zbc_colors.size() - 1);
|
params.format, zbc_colors.size() - 1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -308,11 +308,11 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
|
|||||||
|
|
||||||
if (depth_it != zbc_depths.end()) {
|
if (depth_it != zbc_depths.end()) {
|
||||||
++depth_it->ref_cnt;
|
++depth_it->ref_cnt;
|
||||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused depth entry fmt={:#x}, ref_cnt={:#x}",
|
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: reused depth entry fmt={:#X}, ref_cnt={:#X}",
|
||||||
depth_entry.format, depth_it->ref_cnt);
|
depth_entry.format, depth_it->ref_cnt);
|
||||||
} else {
|
} else {
|
||||||
zbc_depths.push_back(depth_entry);
|
zbc_depths.push_back(depth_entry);
|
||||||
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added depth entry fmt={:#x}, index={:#x}",
|
LOG_DEBUG(Service_NVDRV, "ZBCSetTable: added depth entry fmt={:#X}, index={:#X}",
|
||||||
depth_entry.format, zbc_depths.size() - 1);
|
depth_entry.format, zbc_depths.size() - 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -323,7 +323,7 @@ NvResult nvhost_ctrl_gpu::ZBCSetTable(IoctlZbcSetTable& params) {
|
|||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
|
NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
|
||||||
if (params.type > supported_types) {
|
if (params.type > supported_types) {
|
||||||
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid type {:#x}", params.type);
|
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid type {:#X}", params.type);
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -332,7 +332,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
|
|||||||
switch (static_cast<ZBCTypes>(params.type)) {
|
switch (static_cast<ZBCTypes>(params.type)) {
|
||||||
case ZBCTypes::color: {
|
case ZBCTypes::color: {
|
||||||
if (params.index_size >= zbc_colors.size()) {
|
if (params.index_size >= zbc_colors.size()) {
|
||||||
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid color index {:#x}", params.index_size);
|
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid color index {:#X}", params.index_size);
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -347,7 +347,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
|
|||||||
}
|
}
|
||||||
case ZBCTypes::depth: {
|
case ZBCTypes::depth: {
|
||||||
if (params.index_size >= zbc_depths.size()) {
|
if (params.index_size >= zbc_depths.size()) {
|
||||||
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid depth index {:#x}", params.index_size);
|
LOG_ERROR(Service_NVDRV, "ZBCQueryTable: invalid depth index {:#X}", params.index_size);
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,7 +365,7 @@ NvResult nvhost_ctrl_gpu::ZBCQueryTable(IoctlZbcQueryTable& params) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) {
|
NvResult nvhost_ctrl_gpu::FlushL2(IoctlFlushL2& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called {:#x}", params.flush);
|
LOG_DEBUG(Service_NVDRV, "called {:#X}", params.flush);
|
||||||
// if ((params.flush & 0x01) != 0) //l2 flush
|
// if ((params.flush & 0x01) != 0) //l2 flush
|
||||||
// /* we dont emulate l2 */;
|
// /* we dont emulate l2 */;
|
||||||
// if ((params.flush & 0x04) != 0) //fb flush
|
// if ((params.flush & 0x04) != 0) //fb flush
|
||||||
|
|||||||
@@ -259,7 +259,7 @@ s32_le nvhost_gpu::GetObjectContextClassNumberIndex(CtxClasses class_number) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
|
NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, class_num={:#x}, flags={:#x}, obj_id={:#x}", params.class_num,
|
LOG_DEBUG(Service_NVDRV, "called, class_num={:#X}, flags={:#X}, obj_id={:#X}", params.class_num,
|
||||||
params.flags, params.obj_id);
|
params.flags, params.obj_id);
|
||||||
|
|
||||||
// Do not require channel initialization here: some clients allocate contexts before binding.
|
// Do not require channel initialization here: some clients allocate contexts before binding.
|
||||||
@@ -271,7 +271,7 @@ NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
|
|||||||
std::scoped_lock lk(channel_mutex);
|
std::scoped_lock lk(channel_mutex);
|
||||||
|
|
||||||
if (params.flags) {
|
if (params.flags) {
|
||||||
LOG_WARNING(Service_NVDRV, "non-zero flags={:#x} for class={:#x}", params.flags,
|
LOG_WARNING(Service_NVDRV, "non-zero flags={:#X} for class={:#X}", params.flags,
|
||||||
params.class_num);
|
params.class_num);
|
||||||
|
|
||||||
constexpr u32 allowed_mask{};
|
constexpr u32 allowed_mask{};
|
||||||
@@ -281,13 +281,13 @@ NvResult nvhost_gpu::AllocateObjectContext(IoctlAllocObjCtx& params) {
|
|||||||
s32_le ctx_class_number_index =
|
s32_le ctx_class_number_index =
|
||||||
GetObjectContextClassNumberIndex(static_cast<CtxClasses>(params.class_num));
|
GetObjectContextClassNumberIndex(static_cast<CtxClasses>(params.class_num));
|
||||||
if (ctx_class_number_index < 0) {
|
if (ctx_class_number_index < 0) {
|
||||||
LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#x}",
|
LOG_ERROR(Service_NVDRV, "Invalid class number for object context: {:#X}",
|
||||||
params.class_num);
|
params.class_num);
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctxObjs[ctx_class_number_index].has_value()) {
|
if (ctxObjs[ctx_class_number_index].has_value()) {
|
||||||
LOG_WARNING(Service_NVDRV, "Object context for class {:#x} already allocated on this channel",
|
LOG_WARNING(Service_NVDRV, "Object context for class {:#X} already allocated on this channel",
|
||||||
params.class_num);
|
params.class_num);
|
||||||
return NvResult::AlreadyAllocated;
|
return NvResult::AlreadyAllocated;
|
||||||
}
|
}
|
||||||
@@ -420,20 +420,20 @@ NvResult nvhost_gpu::SubmitGPFIFOBase2(IoctlSubmitGpfifo& params,
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) {
|
NvResult nvhost_gpu::GetWaitbase(IoctlGetWaitbase& params) {
|
||||||
LOG_INFO(Service_NVDRV, "called, unknown={:#x}", params.unknown);
|
LOG_INFO(Service_NVDRV, "called, unknown={:#X}", params.unknown);
|
||||||
|
|
||||||
params.value = 0; // Seems to be hard coded at 0
|
params.value = 0; // Seems to be hard coded at 0
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) {
|
NvResult nvhost_gpu::ChannelSetTimeout(IoctlChannelSetTimeout& params) {
|
||||||
LOG_INFO(Service_NVDRV, "called, timeout={:#x}", params.timeout);
|
LOG_INFO(Service_NVDRV, "called, timeout={:#X}", params.timeout);
|
||||||
|
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) {
|
NvResult nvhost_gpu::ChannelSetTimeslice(IoctlSetTimeslice& params) {
|
||||||
LOG_INFO(Service_NVDRV, "called, timeslice={:#x}", params.timeslice);
|
LOG_INFO(Service_NVDRV, "called, timeslice={:#X}", params.timeslice);
|
||||||
|
|
||||||
if (params.timeslice < 1000 || params.timeslice > 5000) {
|
if (params.timeslice < 1000 || params.timeslice > 5000) {
|
||||||
return NvResult::BadParameter;
|
return NvResult::BadParameter;
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ void nvmap::OnClose(DeviceFD fd) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
NvResult nvmap::IocCreate(IocCreateParams& params) {
|
NvResult nvmap::IocCreate(IocCreateParams& params) {
|
||||||
LOG_DEBUG(Service_NVDRV, "called, size={:#08x}", params.size);
|
LOG_DEBUG(Service_NVDRV, "called, size=0x{:08X}", params.size);
|
||||||
|
|
||||||
std::shared_ptr<NvCore::NvMap::Handle> handle_description{};
|
std::shared_ptr<NvCore::NvMap::Handle> handle_description{};
|
||||||
auto result =
|
auto result =
|
||||||
@@ -92,7 +92,7 @@ NvResult nvmap::IocCreate(IocCreateParams& params) {
|
|||||||
}
|
}
|
||||||
handle_description->orig_size = params.size; // Orig size is the unaligned size
|
handle_description->orig_size = params.size; // Orig size is the unaligned size
|
||||||
params.handle = handle_description->id;
|
params.handle = handle_description->id;
|
||||||
LOG_DEBUG(Service_NVDRV, "handle: {}, size: {:#x}", handle_description->id, params.size);
|
LOG_DEBUG(Service_NVDRV, "handle: {}, size: {:#X}", handle_description->id, params.size);
|
||||||
|
|
||||||
return NvResult::Success;
|
return NvResult::Success;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ void NVDRV::Ioctl1(HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto fd = rp.Pop<DeviceFD>();
|
const auto fd = rp.Pop<DeviceFD>();
|
||||||
const auto command = rp.PopRaw<Ioctl>();
|
const auto command = rp.PopRaw<Ioctl>();
|
||||||
LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl={:#08x}", fd, command.raw);
|
LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw);
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
@@ -85,7 +85,7 @@ void NVDRV::Ioctl2(HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto fd = rp.Pop<DeviceFD>();
|
const auto fd = rp.Pop<DeviceFD>();
|
||||||
const auto command = rp.PopRaw<Ioctl>();
|
const auto command = rp.PopRaw<Ioctl>();
|
||||||
LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl={:#08x}", fd, command.raw);
|
LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw);
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
@@ -112,7 +112,7 @@ void NVDRV::Ioctl3(HLERequestContext& ctx) {
|
|||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
const auto fd = rp.Pop<DeviceFD>();
|
const auto fd = rp.Pop<DeviceFD>();
|
||||||
const auto command = rp.PopRaw<Ioctl>();
|
const auto command = rp.PopRaw<Ioctl>();
|
||||||
LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl={:#08x}", fd, command.raw);
|
LOG_DEBUG(Service_NVDRV, "called fd={}, ioctl=0x{:08X}", fd, command.raw);
|
||||||
|
|
||||||
if (!is_initialized) {
|
if (!is_initialized) {
|
||||||
ServiceError(ctx, NvResult::NotInitialized);
|
ServiceError(ctx, NvResult::NotInitialized);
|
||||||
@@ -212,7 +212,7 @@ void NVDRV::QueryEvent(HLERequestContext& ctx) {
|
|||||||
void NVDRV::SetAruid(HLERequestContext& ctx) {
|
void NVDRV::SetAruid(HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp{ctx};
|
IPC::RequestParser rp{ctx};
|
||||||
pid = rp.Pop<u64>();
|
pid = rp.Pop<u64>();
|
||||||
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#x}", pid);
|
LOG_WARNING(Service_NVDRV, "(STUBBED) called, pid={:#X}", pid);
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 3};
|
IPC::ResponseBuilder rb{ctx, 3};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ Result SteadyClock::IsRtcResetDetected(Out<bool> out_is_detected) {
|
|||||||
|
|
||||||
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
|
Result SteadyClock::GetSetupResultValue(Out<Result> out_result) {
|
||||||
SCOPE_EXIT {
|
SCOPE_EXIT {
|
||||||
LOG_DEBUG(Service_Time, "called. out_result={:#x}", out_result->raw);
|
LOG_DEBUG(Service_Time, "called. out_result={:#X}", out_result->raw);
|
||||||
};
|
};
|
||||||
|
|
||||||
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
R_UNLESS(m_can_write_uninitialized_clock || m_clock_core.IsInitialized(),
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ namespace Service {
|
|||||||
int num_params = (cmd_buf[0] & 0x3F) + ((cmd_buf[0] >> 6) & 0x3F);
|
int num_params = (cmd_buf[0] & 0x3F) + ((cmd_buf[0] >> 6) & 0x3F);
|
||||||
std::string function_string = fmt::format("fn '{}': port={}", name, port_name);
|
std::string function_string = fmt::format("fn '{}': port={}", name, port_name);
|
||||||
for (int i = 1; i <= num_params; ++i)
|
for (int i = 1; i <= num_params; ++i)
|
||||||
function_string += fmt::format(", cmd_buf[{}]={:#x}", i, cmd_buf[i]);
|
function_string += fmt::format(", cmd_buf[{}]={:#X}", i, cmd_buf[i]);
|
||||||
return function_string;
|
return function_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,9 +62,9 @@ void ServiceFrameworkBase::ReportUnimplementedFunction(HLERequestContext& ctx,
|
|||||||
std::string function_name = info == nullptr ? "<unknown>" : info->name;
|
std::string function_name = info == nullptr ? "<unknown>" : info->name;
|
||||||
|
|
||||||
fmt::memory_buffer buf;
|
fmt::memory_buffer buf;
|
||||||
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#x}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]);
|
fmt::format_to(std::back_inserter(buf), "function '{}({})': port='{}' cmd_buf={{[0]={:#X}", ctx.GetCommand(), function_name, service_name, cmd_buf[0]);
|
||||||
for (int i = 1; i <= 8; ++i)
|
for (int i = 1; i <= 8; ++i)
|
||||||
fmt::format_to(std::back_inserter(buf), ", [{}]={:#x}", i, cmd_buf[i]);
|
fmt::format_to(std::back_inserter(buf), ", [{}]={:#X}", i, cmd_buf[i]);
|
||||||
buf.push_back('}');
|
buf.push_back('}');
|
||||||
|
|
||||||
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, service_name);
|
system.GetReporter().SaveUnimplementedFunctionReport(ctx, ctx.GetCommand(), function_name, service_name);
|
||||||
|
|||||||
@@ -89,7 +89,9 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
|
|||||||
for (auto const& e : std::vector<std::pair<std::string_view, void (*)(Core::System&)>>{
|
for (auto const& e : std::vector<std::pair<std::string_view, void (*)(Core::System&)>>{
|
||||||
{"audio", &Audio::LoopProcess},
|
{"audio", &Audio::LoopProcess},
|
||||||
{"FS", &FileSystem::LoopProcess},
|
{"FS", &FileSystem::LoopProcess},
|
||||||
|
{"jit", &JIT::LoopProcess},
|
||||||
{"ldn", &LDN::LoopProcess},
|
{"ldn", &LDN::LoopProcess},
|
||||||
|
{"Loader", &LDR::LoopProcess},
|
||||||
{"nvservices", &Nvidia::LoopProcess},
|
{"nvservices", &Nvidia::LoopProcess},
|
||||||
{"bsdsocket", &Sockets::LoopProcess},
|
{"bsdsocket", &Sockets::LoopProcess},
|
||||||
})
|
})
|
||||||
@@ -118,21 +120,19 @@ Services::Services(std::shared_ptr<SM::ServiceManager>& sm, Core::System& system
|
|||||||
{"glue", &Glue::LoopProcess},
|
{"glue", &Glue::LoopProcess},
|
||||||
{"grc", &GRC::LoopProcess},
|
{"grc", &GRC::LoopProcess},
|
||||||
{"hid", &HID::LoopProcess},
|
{"hid", &HID::LoopProcess},
|
||||||
{"jit", &JIT::LoopProcess},
|
|
||||||
{"lbl", &LBL::LoopProcess},
|
{"lbl", &LBL::LoopProcess},
|
||||||
{"Loader", &LDR::LoopProcess},
|
|
||||||
{"LogManager.Prod", &LM::LoopProcess},
|
{"LogManager.Prod", &LM::LoopProcess},
|
||||||
{"mig", &Migration::LoopProcess},
|
{"mig", &Migration::LoopProcess},
|
||||||
{"mii", &Mii::LoopProcess},
|
{"mii", &Mii::LoopProcess},
|
||||||
{"mm", &MM::LoopProcess},
|
{"mm", &MM::LoopProcess},
|
||||||
{"mnpp", &MNPP::LoopProcess},
|
{"mnpp", &MNPP::LoopProcess},
|
||||||
|
{"nvnflinger", &Nvnflinger::LoopProcess},
|
||||||
{"NCM", &NCM::LoopProcess},
|
{"NCM", &NCM::LoopProcess},
|
||||||
{"nfc", &NFC::LoopProcess},
|
{"nfc", &NFC::LoopProcess},
|
||||||
{"nfp", &NFP::LoopProcess},
|
{"nfp", &NFP::LoopProcess},
|
||||||
{"ngc", &NGC::LoopProcess},
|
{"ngc", &NGC::LoopProcess},
|
||||||
{"nifm", &NIFM::LoopProcess},
|
{"nifm", &NIFM::LoopProcess},
|
||||||
{"nim", &NIM::LoopProcess},
|
{"nim", &NIM::LoopProcess},
|
||||||
{"nvnflinger", &Nvnflinger::LoopProcess},
|
|
||||||
{"npns", &NPNS::LoopProcess},
|
{"npns", &NPNS::LoopProcess},
|
||||||
{"ns", &NS::LoopProcess},
|
{"ns", &NS::LoopProcess},
|
||||||
{"olsc", &OLSC::LoopProcess},
|
{"olsc", &OLSC::LoopProcess},
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ Result SM::GetServiceImpl(Kernel::KClientSession** out_client_session, HLEReques
|
|||||||
// Create a new session.
|
// Create a new session.
|
||||||
Kernel::KClientSession* session{};
|
Kernel::KClientSession* session{};
|
||||||
if (const auto result = client_port->CreateSession(kernel, &session); result.IsError()) {
|
if (const auto result = client_port->CreateSession(kernel, &session); result.IsError()) {
|
||||||
LOG_ERROR(Service_SM, "called service={} -> error {:#08x}", name, result.raw);
|
LOG_ERROR(Service_SM, "called service={} -> error 0x{:08X}", name, result.raw);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -283,7 +283,7 @@ void BSD::GetSockOpt(HLERequestContext& ctx) {
|
|||||||
|
|
||||||
std::vector<u8> optval(ctx.GetWriteBufferSize());
|
std::vector<u8> optval(ctx.GetWriteBufferSize());
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called. fd={} level={} optname={:#x} len={:#x}", fd, level, optname,
|
LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} len=0x{:x}", fd, level, optname,
|
||||||
optval.size());
|
optval.size());
|
||||||
|
|
||||||
const Errno err = GetSockOptImpl(fd, level, optname, optval);
|
const Errno err = GetSockOptImpl(fd, level, optname, optval);
|
||||||
@@ -331,7 +331,7 @@ void BSD::SetSockOpt(HLERequestContext& ctx) {
|
|||||||
const OptName optname = static_cast<OptName>(rp.Pop<u32>());
|
const OptName optname = static_cast<OptName>(rp.Pop<u32>());
|
||||||
const auto optval = ctx.ReadBuffer();
|
const auto optval = ctx.ReadBuffer();
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called. fd={} level={} optname={:#x} optlen={}", fd, level,
|
LOG_DEBUG(Service, "called. fd={} level={} optname=0x{:x} optlen={}", fd, level,
|
||||||
static_cast<u32>(optname), optval.size());
|
static_cast<u32>(optname), optval.size());
|
||||||
|
|
||||||
BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
|
BuildErrnoResponse(ctx, SetSockOptImpl(fd, level, optname, optval));
|
||||||
@@ -354,7 +354,7 @@ void BSD::Recv(HLERequestContext& ctx) {
|
|||||||
const s32 fd = rp.Pop<s32>();
|
const s32 fd = rp.Pop<s32>();
|
||||||
const u32 flags = rp.Pop<u32>();
|
const u32 flags = rp.Pop<u32>();
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called. fd={} flags={:#x} len={}", fd, flags, ctx.GetWriteBufferSize());
|
LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetWriteBufferSize());
|
||||||
|
|
||||||
ExecuteWork(ctx, RecvWork{
|
ExecuteWork(ctx, RecvWork{
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
@@ -369,7 +369,7 @@ void BSD::RecvFrom(HLERequestContext& ctx) {
|
|||||||
const s32 fd = rp.Pop<s32>();
|
const s32 fd = rp.Pop<s32>();
|
||||||
const u32 flags = rp.Pop<u32>();
|
const u32 flags = rp.Pop<u32>();
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called. fd={} flags={:#x} len={} addrlen={}", fd, flags,
|
LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={} addrlen={}", fd, flags,
|
||||||
ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1));
|
ctx.GetWriteBufferSize(0), ctx.GetWriteBufferSize(1));
|
||||||
|
|
||||||
ExecuteWork(ctx, RecvFromWork{
|
ExecuteWork(ctx, RecvFromWork{
|
||||||
@@ -386,7 +386,7 @@ void BSD::Send(HLERequestContext& ctx) {
|
|||||||
const s32 fd = rp.Pop<s32>();
|
const s32 fd = rp.Pop<s32>();
|
||||||
const u32 flags = rp.Pop<u32>();
|
const u32 flags = rp.Pop<u32>();
|
||||||
|
|
||||||
LOG_DEBUG(Service, "called. fd={} flags={:#x} len={}", fd, flags, ctx.GetReadBufferSize());
|
LOG_DEBUG(Service, "called. fd={} flags=0x{:x} len={}", fd, flags, ctx.GetReadBufferSize());
|
||||||
|
|
||||||
ExecuteWork(ctx, SendWork{
|
ExecuteWork(ctx, SendWork{
|
||||||
.fd = fd,
|
.fd = fd,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
@@ -141,7 +141,7 @@ Result IApplicationDisplayService::GetDisplayResolution(Out<s64> out_width, Out<
|
|||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) {
|
Result IApplicationDisplayService::SetLayerScalingMode(NintendoScaleMode scale_mode, u64 layer_id) {
|
||||||
LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown={:#016x}", scale_mode, layer_id);
|
LOG_DEBUG(Service_VI, "called. scale_mode={}, unknown=0x{:016X}", scale_mode, layer_id);
|
||||||
|
|
||||||
if (scale_mode > NintendoScaleMode::PreserveAspectRatio) {
|
if (scale_mode > NintendoScaleMode::PreserveAspectRatio) {
|
||||||
LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
|
LOG_ERROR(Service_VI, "Invalid scaling mode provided.");
|
||||||
|
|||||||
@@ -652,13 +652,13 @@ short TranslatePollEvents(PollEvents events) {
|
|||||||
// Unlike poll on other OSes, WSAPoll will complain if any other flags are set on input.
|
// Unlike poll on other OSes, WSAPoll will complain if any other flags are set on input.
|
||||||
if (result & ~allowed_events) {
|
if (result & ~allowed_events) {
|
||||||
LOG_DEBUG(Network,
|
LOG_DEBUG(Network,
|
||||||
"Removing WSAPoll input events {:#x} because Windows doesn't support them",
|
"Removing WSAPoll input events 0x{:x} because Windows doesn't support them",
|
||||||
result & ~allowed_events);
|
result & ~allowed_events);
|
||||||
}
|
}
|
||||||
result &= allowed_events;
|
result &= allowed_events;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UNIMPLEMENTED_IF_MSG((u16)events != 0, "Unhandled guest events={:#x}", (u16)events);
|
UNIMPLEMENTED_IF_MSG((u16)events != 0, "Unhandled guest events=0x{:x}", (u16)events);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -682,7 +682,7 @@ PollEvents TranslatePollRevents(short revents) {
|
|||||||
translate(POLLRDBAND, PollEvents::RdBand);
|
translate(POLLRDBAND, PollEvents::RdBand);
|
||||||
translate(POLLWRBAND, PollEvents::WrBand);
|
translate(POLLWRBAND, PollEvents::WrBand);
|
||||||
|
|
||||||
UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents={:#x}", revents);
|
UNIMPLEMENTED_IF_MSG(revents != 0, "Unhandled host revents=0x{:x}", revents);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -263,7 +263,7 @@ AppLoader_DeconstructedRomDirectory::LoadResult AppLoader_DeconstructedRomDirect
|
|||||||
|
|
||||||
next_load_addr = *tentative_next_load_addr;
|
next_load_addr = *tentative_next_load_addr;
|
||||||
modules.insert_or_assign(load_addr, module);
|
modules.insert_or_assign(load_addr, module);
|
||||||
LOG_DEBUG(Loader, "loaded module {} @ {:#x}", module, load_addr);
|
LOG_DEBUG(Loader, "loaded module {} @ {:#X}", module, load_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
|
|||||||
const VAddr base_address = GetInteger(process.GetEntryPoint());
|
const VAddr base_address = GetInteger(process.GetEntryPoint());
|
||||||
process.LoadModule(system.Kernel(), std::move(codeset), base_address);
|
process.LoadModule(system.Kernel(), std::move(codeset), base_address);
|
||||||
|
|
||||||
LOG_DEBUG(Loader, "loaded module {} @ {:#x}", kip->GetName(), base_address);
|
LOG_DEBUG(Loader, "loaded module {} @ {:#X}", kip->GetName(), base_address);
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return {ResultStatus::Success,
|
return {ResultStatus::Success,
|
||||||
|
|||||||
@@ -235,7 +235,7 @@ AppLoader_NSO::LoadResult AppLoader_NSO::Load(Kernel::KProcess& process, Core::S
|
|||||||
}
|
}
|
||||||
|
|
||||||
modules.insert_or_assign(base_address, file->GetName());
|
modules.insert_or_assign(base_address, file->GetName());
|
||||||
LOG_DEBUG(Loader, "loaded module {} @ {:#x}", file->GetName(), base_address);
|
LOG_DEBUG(Loader, "loaded module {} @ {:#X}", file->GetName(), base_address);
|
||||||
|
|
||||||
is_loaded = true;
|
is_loaded = true;
|
||||||
return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority,
|
return {ResultStatus::Success, LoadParameters{Kernel::KThread::DefaultThreadPriority,
|
||||||
|
|||||||
+10
-10
@@ -282,7 +282,7 @@ struct Memory::Impl {
|
|||||||
bool ReadBlockImpl(const Common::ProcessAddress addr, void* buffer, const std::size_t size, bool unsafe) {
|
bool ReadBlockImpl(const Common::ProcessAddress addr, void* buffer, const std::size_t size, bool unsafe) {
|
||||||
return WalkBlock(addr, size,
|
return WalkBlock(addr, size,
|
||||||
[addr, size, &buffer](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
[addr, size, &buffer](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped @ {:#016x} (start address = {:#016x}, size = {})", GetInteger(current_vaddr), GetInteger(addr), size);
|
LOG_ERROR(HW_Memory, "Unmapped @ {:#016X} (start address = {:#016X}, size = {})", GetInteger(current_vaddr), GetInteger(addr), size);
|
||||||
std::memset(reinterpret_cast<u8*>(buffer) + offset, 0, copy_amount);
|
std::memset(reinterpret_cast<u8*>(buffer) + offset, 0, copy_amount);
|
||||||
},
|
},
|
||||||
[&](const std::size_t offset, const std::size_t copy_amount, const u8* const ptr) {
|
[&](const std::size_t offset, const std::size_t copy_amount, const u8* const ptr) {
|
||||||
@@ -306,7 +306,7 @@ struct Memory::Impl {
|
|||||||
bool WriteBlockImpl(const Common::ProcessAddress addr, const void* buffer, const std::size_t size, bool unsafe) {
|
bool WriteBlockImpl(const Common::ProcessAddress addr, const void* buffer, const std::size_t size, bool unsafe) {
|
||||||
return WalkBlock(addr, size,
|
return WalkBlock(addr, size,
|
||||||
[addr, size](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
[addr, size](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped @ {:#016x} (start address = {:#016x}, size = {})", GetInteger(current_vaddr), GetInteger(addr), size);
|
LOG_ERROR(HW_Memory, "Unmapped @ 0x{:016X} (start address = 0x{:016X}, size = {})", GetInteger(current_vaddr), GetInteger(addr), size);
|
||||||
},
|
},
|
||||||
[&](const std::size_t offset, const std::size_t copy_amount, u8* const ptr) {
|
[&](const std::size_t offset, const std::size_t copy_amount, u8* const ptr) {
|
||||||
std::memcpy(ptr, reinterpret_cast<u8 const*>(buffer) + offset, copy_amount);
|
std::memcpy(ptr, reinterpret_cast<u8 const*>(buffer) + offset, copy_amount);
|
||||||
@@ -322,7 +322,7 @@ struct Memory::Impl {
|
|||||||
bool ZeroBlock(const Common::ProcessAddress addr, const std::size_t size) {
|
bool ZeroBlock(const Common::ProcessAddress addr, const std::size_t size) {
|
||||||
return WalkBlock(addr, size,
|
return WalkBlock(addr, size,
|
||||||
[addr, size](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
[addr, size](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped @ {:#016x} (start address = {:#016x}, size = {})", GetInteger(current_vaddr), GetInteger(addr), size);
|
LOG_ERROR(HW_Memory, "Unmapped @ {:#016X} (start address = {:#016X}, size = {})", GetInteger(current_vaddr), GetInteger(addr), size);
|
||||||
},
|
},
|
||||||
[=](const std::size_t offset, const std::size_t copy_amount, u8* const ptr) {
|
[=](const std::size_t offset, const std::size_t copy_amount, u8* const ptr) {
|
||||||
std::memset(ptr, 0, copy_amount);
|
std::memset(ptr, 0, copy_amount);
|
||||||
@@ -336,7 +336,7 @@ struct Memory::Impl {
|
|||||||
bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, const std::size_t size) {
|
bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, const std::size_t size) {
|
||||||
return WalkBlock(dest_addr, size,
|
return WalkBlock(dest_addr, size,
|
||||||
[&](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
[&](const std::size_t offset, const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped @ {:#016x} (start address = {:#016x}, size = {})", GetInteger(current_vaddr), GetInteger(src_addr), size);
|
LOG_ERROR(HW_Memory, "Unmapped @ {:#016X} (start address = {:#016X}, size = {})", GetInteger(current_vaddr), GetInteger(src_addr), size);
|
||||||
ZeroBlock(dest_addr + offset, copy_amount);
|
ZeroBlock(dest_addr + offset, copy_amount);
|
||||||
},
|
},
|
||||||
[&](const std::size_t offset, const std::size_t copy_amount, const u8* const ptr) {
|
[&](const std::size_t offset, const std::size_t copy_amount, const u8* const ptr) {
|
||||||
@@ -575,7 +575,7 @@ struct Memory::Impl {
|
|||||||
} else {
|
} else {
|
||||||
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
|
switch (Common::PageTable::PageInfo::ExtractType(raw_pointer)) {
|
||||||
case Common::PageType::Memory:
|
case Common::PageType::Memory:
|
||||||
ASSERT_MSG(false, "Mapped memory page without a pointer @ {:#016x}", vaddr);
|
ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
|
||||||
return nullptr;
|
return nullptr;
|
||||||
case Common::PageType::DebugMemory:
|
case Common::PageType::DebugMemory:
|
||||||
return GetPointerFromDebugMemory(vaddr);
|
return GetPointerFromDebugMemory(vaddr);
|
||||||
@@ -603,7 +603,7 @@ struct Memory::Impl {
|
|||||||
return GetPointerImpl(
|
return GetPointerImpl(
|
||||||
GetInteger(vaddr),
|
GetInteger(vaddr),
|
||||||
[vaddr]() {
|
[vaddr]() {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped GetPointer @ {:#016x}", GetInteger(vaddr));
|
LOG_ERROR(HW_Memory, "Unmapped GetPointer @ 0x{:016X}", GetInteger(vaddr));
|
||||||
},
|
},
|
||||||
[]() {});
|
[]() {});
|
||||||
}
|
}
|
||||||
@@ -621,7 +621,7 @@ struct Memory::Impl {
|
|||||||
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) {
|
inline T Read(Common::ProcessAddress vaddr) noexcept requires(std::is_trivially_copyable_v<T>) {
|
||||||
const u64 addr = GetInteger(vaddr);
|
const u64 addr = GetInteger(vaddr);
|
||||||
if (auto const ptr = GetPointerImpl(addr, [addr]() {
|
if (auto const ptr = GetPointerImpl(addr, [addr]() {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped Read{} @ {:#016x}", sizeof(T) * 8, addr);
|
LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:016X}", sizeof(T) * 8, addr);
|
||||||
}, [&]() {
|
}, [&]() {
|
||||||
HandleRasterizerDownload(addr, sizeof(T));
|
HandleRasterizerDownload(addr, sizeof(T));
|
||||||
}); ptr) [[likely]] {
|
}); ptr) [[likely]] {
|
||||||
@@ -642,7 +642,7 @@ struct Memory::Impl {
|
|||||||
inline void Write(Common::ProcessAddress vaddr, const T data) noexcept requires(std::is_trivially_copyable_v<T>) {
|
inline void Write(Common::ProcessAddress vaddr, const T data) noexcept requires(std::is_trivially_copyable_v<T>) {
|
||||||
const u64 addr = GetInteger(vaddr);
|
const u64 addr = GetInteger(vaddr);
|
||||||
if (auto const ptr = GetPointerImpl(addr, [addr, data]() {
|
if (auto const ptr = GetPointerImpl(addr, [addr, data]() {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped Write{} @ {:#016x} = {:#016x}", sizeof(T) * 8, addr, u64(data));
|
LOG_ERROR(HW_Memory, "Unmapped Write{} @ 0x{:016X} = 0x{:016X}", sizeof(T) * 8, addr, u64(data));
|
||||||
}, [&]() { HandleRasterizerWrite(addr, sizeof(T)); }); ptr) [[likely]]
|
}, [&]() { HandleRasterizerWrite(addr, sizeof(T)); }); ptr) [[likely]]
|
||||||
std::memcpy(ptr, &data, sizeof(T));
|
std::memcpy(ptr, &data, sizeof(T));
|
||||||
}
|
}
|
||||||
@@ -652,7 +652,7 @@ struct Memory::Impl {
|
|||||||
u8* const ptr = GetPointerImpl(
|
u8* const ptr = GetPointerImpl(
|
||||||
GetInteger(vaddr),
|
GetInteger(vaddr),
|
||||||
[vaddr, data]() {
|
[vaddr, data]() {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ {:#016x} = {:#016x}",
|
LOG_ERROR(HW_Memory, "Unmapped WriteExclusive{} @ 0x{:016X} = 0x{:016X}",
|
||||||
sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data));
|
sizeof(T) * 8, GetInteger(vaddr), static_cast<u64>(data));
|
||||||
},
|
},
|
||||||
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); });
|
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(T)); });
|
||||||
@@ -666,7 +666,7 @@ struct Memory::Impl {
|
|||||||
u8* const ptr = GetPointerImpl(
|
u8* const ptr = GetPointerImpl(
|
||||||
GetInteger(vaddr),
|
GetInteger(vaddr),
|
||||||
[vaddr, data]() {
|
[vaddr, data]() {
|
||||||
LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ {:#016x} = {:#016x}{:016X}",
|
LOG_ERROR(HW_Memory, "Unmapped WriteExclusive128 @ 0x{:016X} = 0x{:016X}{:016X}",
|
||||||
GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0]));
|
GetInteger(vaddr), static_cast<u64>(data[1]), static_cast<u64>(data[0]));
|
||||||
},
|
},
|
||||||
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); });
|
[&]() { HandleRasterizerWrite(GetInteger(vaddr), sizeof(u128)); });
|
||||||
|
|||||||
@@ -34,8 +34,7 @@ oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext&, IR::Cond co
|
|||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32LeafTerminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
|
||||||
|
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||||
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
||||||
@@ -126,53 +125,31 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Fa
|
|||||||
|
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
oaknut::Label pass = EmitA32Cond(code, ctx, terminal.if_);
|
oaknut::Label pass = EmitA32Cond(code, ctx, terminal.if_);
|
||||||
EmitA32LeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA32Terminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
code.l(pass);
|
code.l(pass);
|
||||||
EmitA32LeafTerminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
EmitA32Terminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
oaknut::Label fail;
|
oaknut::Label fail;
|
||||||
code.LDRB(Wscratch0, SP, offsetof(StackLayout, check_bit));
|
code.LDRB(Wscratch0, SP, offsetof(StackLayout, check_bit));
|
||||||
code.CBZ(Wscratch0, fail);
|
code.CBZ(Wscratch0, fail);
|
||||||
EmitA32LeafTerminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
EmitA32Terminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
||||||
code.l(fail);
|
code.l(fail);
|
||||||
EmitA32LeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA32Terminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
oaknut::Label fail;
|
oaknut::Label fail;
|
||||||
code.LDAR(Wscratch0, Xhalt);
|
code.LDAR(Wscratch0, Xhalt);
|
||||||
code.CBNZ(Wscratch0, fail);
|
code.CBNZ(Wscratch0, fail);
|
||||||
EmitA32LeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA32Terminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
code.l(fail);
|
code.l(fail);
|
||||||
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32LeafTerminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
boost::apply_visitor([&](const auto& t) { EmitA32Terminal(code, ctx, t, initial_location, is_single_step); }, terminal);
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
|
||||||
if (auto const x = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
|
||||||
return EmitA32LeafTerminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
|
||||||
return EmitA32Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
|
||||||
|
|||||||
@@ -33,8 +33,7 @@ oaknut::Label EmitA64Cond(oaknut::CodeGenerator& code, EmitContext&, IR::Cond co
|
|||||||
return pass;
|
return pass;
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA64LeafTerminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
|
||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||||
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
||||||
@@ -109,53 +108,31 @@ void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Fa
|
|||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
oaknut::Label pass = EmitA64Cond(code, ctx, terminal.if_);
|
oaknut::Label pass = EmitA64Cond(code, ctx, terminal.if_);
|
||||||
EmitA64LeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA64Terminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
code.l(pass);
|
code.l(pass);
|
||||||
EmitA64LeafTerminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
EmitA64Terminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
oaknut::Label fail;
|
oaknut::Label fail;
|
||||||
code.LDRB(Wscratch0, SP, offsetof(StackLayout, check_bit));
|
code.LDRB(Wscratch0, SP, offsetof(StackLayout, check_bit));
|
||||||
code.CBZ(Wscratch0, fail);
|
code.CBZ(Wscratch0, fail);
|
||||||
EmitA64LeafTerminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
EmitA64Terminal(code, ctx, terminal.then_, initial_location, is_single_step);
|
||||||
code.l(fail);
|
code.l(fail);
|
||||||
EmitA64LeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA64Terminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
oaknut::Label fail;
|
oaknut::Label fail;
|
||||||
code.LDAR(Wscratch0, Xhalt);
|
code.LDAR(Wscratch0, Xhalt);
|
||||||
code.CBNZ(Wscratch0, fail);
|
code.CBNZ(Wscratch0, fail);
|
||||||
EmitA64LeafTerminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA64Terminal(code, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
code.l(fail);
|
code.l(fail);
|
||||||
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA64LeafTerminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
boost::apply_visitor([&](const auto& t) { EmitA64Terminal(code, ctx, t, initial_location, is_single_step); }, terminal);
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
|
||||||
if (auto const x = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
|
||||||
return EmitA64LeafTerminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
|
||||||
return EmitA64Terminal(code, ctx, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx) {
|
||||||
|
|||||||
@@ -112,7 +112,6 @@ void EmitA32Cond(biscuit::Assembler& as, EmitContext&, IR::Cond cond, biscuit::L
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32LeafTerminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::LeafTerminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
|
||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step);
|
||||||
|
|
||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||||
@@ -171,18 +170,18 @@ void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::FastDis
|
|||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
biscuit::Label pass;
|
biscuit::Label pass;
|
||||||
EmitA32Cond(as, ctx, terminal.if_, &pass);
|
EmitA32Cond(as, ctx, terminal.if_, &pass);
|
||||||
EmitA32LeafTerminal(as, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA32Terminal(as, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
as.Bind(&pass);
|
as.Bind(&pass);
|
||||||
EmitA32LeafTerminal(as, ctx, terminal.then_, initial_location, is_single_step);
|
EmitA32Terminal(as, ctx, terminal.then_, initial_location, is_single_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
biscuit::Label fail;
|
biscuit::Label fail;
|
||||||
as.LBU(Xscratch0, offsetof(StackLayout, check_bit), Xstate);
|
as.LBU(Xscratch0, offsetof(StackLayout, check_bit), Xstate);
|
||||||
as.BEQZ(Xscratch0, &fail);
|
as.BEQZ(Xscratch0, &fail);
|
||||||
EmitA32LeafTerminal(as, ctx, terminal.then_, initial_location, is_single_step);
|
EmitA32Terminal(as, ctx, terminal.then_, initial_location, is_single_step);
|
||||||
as.Bind(&fail);
|
as.Bind(&fail);
|
||||||
EmitA32LeafTerminal(as, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA32Terminal(as, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
@@ -190,35 +189,13 @@ void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::CheckHa
|
|||||||
as.LWU(Xscratch0, 0, Xhalt);
|
as.LWU(Xscratch0, 0, Xhalt);
|
||||||
as.FENCE(biscuit::FenceOrder::RW, biscuit::FenceOrder::RW);
|
as.FENCE(biscuit::FenceOrder::RW, biscuit::FenceOrder::RW);
|
||||||
as.BNEZ(Xscratch0, &fail);
|
as.BNEZ(Xscratch0, &fail);
|
||||||
EmitA32LeafTerminal(as, ctx, terminal.else_, initial_location, is_single_step);
|
EmitA32Terminal(as, ctx, terminal.else_, initial_location, is_single_step);
|
||||||
as.Bind(&fail);
|
as.Bind(&fail);
|
||||||
EmitRelocation(as, ctx, LinkTarget::ReturnFromRunCode);
|
EmitRelocation(as, ctx, LinkTarget::ReturnFromRunCode);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32LeafTerminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::LeafTerminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
|
||||||
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
|
||||||
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
|
||||||
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
|
|
||||||
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
|
|
||||||
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
|
|
||||||
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
|
|
||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx, IR::Term::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
if (auto const x = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
boost::apply_visitor([&](const auto& t) { EmitA32Terminal(as, ctx, t, initial_location, is_single_step); }, terminal);
|
||||||
return EmitA32LeafTerminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
|
||||||
return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
|
||||||
return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
|
||||||
return EmitA32Terminal(as, ctx, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx) {
|
void EmitA32Terminal(biscuit::Assembler& as, EmitContext& ctx) {
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ finish_this_inst:
|
|||||||
if (conf.enable_cycle_counting)
|
if (conf.enable_cycle_counting)
|
||||||
EmitAddCycles(block.CycleCount());
|
EmitAddCycles(block.CycleCount());
|
||||||
code.mov(rbp, code.qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, abi_base_pointer)]);
|
code.mov(rbp, code.qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, abi_base_pointer)]);
|
||||||
EmitTerminal(block.terminal, ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
|
EmitTerminal(block.GetTerminal(), ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
|
||||||
code.int3();
|
code.int3();
|
||||||
|
|
||||||
for (auto& deferred_emit : ctx.deferred_emits)
|
for (auto& deferred_emit : ctx.deferred_emits)
|
||||||
@@ -219,7 +219,7 @@ void A32EmitX64::EmitCondPrelude(const A32EmitContext& ctx) {
|
|||||||
if (conf.enable_cycle_counting) {
|
if (conf.enable_cycle_counting) {
|
||||||
EmitAddCycles(ctx.block.ConditionFailedCycleCount());
|
EmitAddCycles(ctx.block.ConditionFailedCycleCount());
|
||||||
}
|
}
|
||||||
EmitLeafTerminal(IR::Term::LinkBlock{ctx.block.ConditionFailedLocation()}, ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
|
EmitTerminal(IR::Term::LinkBlock{ctx.block.ConditionFailedLocation()}, ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
|
||||||
code.L(pass);
|
code.L(pass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1155,12 +1155,11 @@ void A32EmitX64::EmitSetUpperLocationDescriptor(IR::LocationDescriptor new_locat
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
e.EmitSetUpperLocationDescriptor(terminal.next, initial_location);
|
e.EmitSetUpperLocationDescriptor(terminal.next, initial_location);
|
||||||
if (!e.conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) {
|
if (!e.conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) {
|
||||||
e.code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC());
|
e.code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC());
|
||||||
@@ -1187,10 +1186,9 @@ bool EmitTerminalImpl(A32EmitX64& e, IR::Term::LinkBlock terminal, IR::LocationD
|
|||||||
e.PushRSBHelper(rax, rbx, terminal.next);
|
e.PushRSBHelper(rax, rbx, terminal.next);
|
||||||
e.code.ForceReturnFromRunCode();
|
e.code.ForceReturnFromRunCode();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
e.EmitSetUpperLocationDescriptor(terminal.next, initial_location);
|
e.EmitSetUpperLocationDescriptor(terminal.next, initial_location);
|
||||||
if (!e.conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) {
|
if (!e.conf.HasOptimization(OptimizationFlag::BlockLinking) || is_single_step) {
|
||||||
e.code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC());
|
e.code.mov(MJitStateReg(A32::Reg::PC), A32::LocationDescriptor{terminal.next}.PC());
|
||||||
@@ -1203,78 +1201,55 @@ bool EmitTerminalImpl(A32EmitX64& e, IR::Term::LinkBlockFast terminal, IR::Locat
|
|||||||
e.EmitPatchJmp(terminal.next);
|
e.EmitPatchJmp(terminal.next);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::PopRSBHint, IR::LocationDescriptor, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::PopRSBHint, IR::LocationDescriptor, bool is_single_step) {
|
||||||
if (!e.conf.HasOptimization(OptimizationFlag::ReturnStackBuffer) || is_single_step) {
|
if (!e.conf.HasOptimization(OptimizationFlag::ReturnStackBuffer) || is_single_step) {
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
} else {
|
} else {
|
||||||
e.code.jmp(e.terminal_handler_pop_rsb_hint);
|
e.code.jmp(e.terminal_handler_pop_rsb_hint);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool is_single_step) {
|
||||||
if (!e.conf.HasOptimization(OptimizationFlag::FastDispatch) || is_single_step) {
|
if (!e.conf.HasOptimization(OptimizationFlag::FastDispatch) || is_single_step) {
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
} else {
|
} else {
|
||||||
e.code.jmp(e.terminal_handler_fast_dispatch_hint);
|
e.code.jmp(e.terminal_handler_fast_dispatch_hint);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
Xbyak::Label pass = e.EmitCond(terminal.if_);
|
Xbyak::Label pass = e.EmitCond(terminal.if_);
|
||||||
e.EmitLeafTerminal(terminal.else_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.else_, initial_location, is_single_step);
|
||||||
e.code.L(pass);
|
e.code.L(pass);
|
||||||
e.EmitLeafTerminal(terminal.then_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.then_, initial_location, is_single_step);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
Xbyak::Label fail;
|
Xbyak::Label fail;
|
||||||
e.code.cmp(e.code.byte[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, check_bit)], u8(0));
|
e.code.cmp(e.code.byte[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, check_bit)], u8(0));
|
||||||
e.code.jz(fail);
|
e.code.jz(fail);
|
||||||
e.EmitLeafTerminal(terminal.then_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.then_, initial_location, is_single_step);
|
||||||
e.code.L(fail);
|
e.code.L(fail);
|
||||||
e.EmitLeafTerminal(terminal.else_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.else_, initial_location, is_single_step);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A32EmitX64& e, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A32EmitX64& e, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
e.code.cmp(dword[e.code.ABI_JIT_PTR + offsetof(A32JitState, halt_reason)], 0);
|
e.code.cmp(dword[e.code.ABI_JIT_PTR + offsetof(A32JitState, halt_reason)], 0);
|
||||||
e.code.jne(e.code.GetForceReturnFromRunCodeAddress());
|
e.code.jne(e.code.GetForceReturnFromRunCodeAddress());
|
||||||
e.EmitLeafTerminal(terminal.else_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.else_, initial_location, is_single_step);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
void EmitTerminalImpl(A32EmitX64&, IR::Term::Invalid, IR::LocationDescriptor, bool) {
|
||||||
|
|
||||||
bool A32EmitX64::EmitLeafTerminal(IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept {
|
|
||||||
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool A32EmitX64::EmitTerminal(IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept {
|
void A32EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept {
|
||||||
if (auto const e = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
boost::apply_visitor([this, initial_location, is_single_step](auto x) {
|
||||||
return EmitLeafTerminal(*e, initial_location, is_single_step);
|
EmitTerminalImpl(*this, x, initial_location, is_single_step);
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
}, terminal);
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void A32EmitX64::EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr) {
|
void A32EmitX64::EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr) {
|
||||||
|
|||||||
@@ -112,8 +112,7 @@ public:
|
|||||||
|
|
||||||
// Terminal instruction emitters
|
// Terminal instruction emitters
|
||||||
void EmitSetUpperLocationDescriptor(IR::LocationDescriptor new_location, IR::LocationDescriptor old_location);
|
void EmitSetUpperLocationDescriptor(IR::LocationDescriptor new_location, IR::LocationDescriptor old_location);
|
||||||
bool EmitLeafTerminal(IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept override;
|
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept override;
|
||||||
bool EmitTerminal(IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept override;
|
|
||||||
|
|
||||||
// Patching
|
// Patching
|
||||||
void Unpatch(const IR::LocationDescriptor& target_desc) override;
|
void Unpatch(const IR::LocationDescriptor& target_desc) override;
|
||||||
|
|||||||
@@ -12,7 +12,6 @@
|
|||||||
#include <fmt/ostream.h>
|
#include <fmt/ostream.h>
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
#include "dynarmic/ir/terminal.h"
|
|
||||||
#include "dynarmic/mcl/integer_of_size.hpp"
|
#include "dynarmic/mcl/integer_of_size.hpp"
|
||||||
#include <boost/container/static_vector.hpp>
|
#include <boost/container/static_vector.hpp>
|
||||||
|
|
||||||
@@ -148,7 +147,7 @@ finish_this_inst:
|
|||||||
if (conf.enable_cycle_counting)
|
if (conf.enable_cycle_counting)
|
||||||
EmitAddCycles(block.CycleCount());
|
EmitAddCycles(block.CycleCount());
|
||||||
code.mov(rbp, code.qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, abi_base_pointer)]);
|
code.mov(rbp, code.qword[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, abi_base_pointer)]);
|
||||||
EmitTerminal(block.terminal, ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
|
EmitTerminal(block.GetTerminal(), ctx.Location().SetSingleStepping(false), ctx.IsSingleStep());
|
||||||
code.int3();
|
code.int3();
|
||||||
for (auto& deferred_emit : ctx.deferred_emits)
|
for (auto& deferred_emit : ctx.deferred_emits)
|
||||||
deferred_emit();
|
deferred_emit();
|
||||||
@@ -618,12 +617,11 @@ std::string A64EmitX64::LocationDescriptorToFriendlyName(const IR::LocationDescr
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::ReturnToDispatch, IR::LocationDescriptor, bool) {
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::LinkBlock terminal, IR::LocationDescriptor, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::LinkBlock terminal, IR::LocationDescriptor, bool is_single_step) {
|
||||||
// Used for patches and linking
|
// Used for patches and linking
|
||||||
if (e.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
if (e.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
||||||
if (e.conf.enable_cycle_counting) {
|
if (e.conf.enable_cycle_counting) {
|
||||||
@@ -651,10 +649,9 @@ bool EmitTerminalImpl(A64EmitX64& e, IR::Term::LinkBlock terminal, IR::LocationD
|
|||||||
e.code.mov(qword[e.code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax);
|
e.code.mov(qword[e.code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax);
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor, bool is_single_step) {
|
||||||
if (e.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
if (e.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
||||||
e.patch_information[terminal.next].jmp.push_back(e.code.getCurr());
|
e.patch_information[terminal.next].jmp.push_back(e.code.getCurr());
|
||||||
if (auto next_bb = e.GetBasicBlock(terminal.next)) {
|
if (auto next_bb = e.GetBasicBlock(terminal.next)) {
|
||||||
@@ -667,86 +664,63 @@ bool EmitTerminalImpl(A64EmitX64& e, IR::Term::LinkBlockFast terminal, IR::Locat
|
|||||||
e.code.mov(qword[e.code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax);
|
e.code.mov(qword[e.code.ABI_JIT_PTR + offsetof(A64JitState, pc)], rax);
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::PopRSBHint, IR::LocationDescriptor, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::PopRSBHint, IR::LocationDescriptor, bool is_single_step) {
|
||||||
if (e.conf.HasOptimization(OptimizationFlag::ReturnStackBuffer) && !is_single_step) {
|
if (e.conf.HasOptimization(OptimizationFlag::ReturnStackBuffer) && !is_single_step) {
|
||||||
e.code.jmp(e.terminal_handler_pop_rsb_hint);
|
e.code.jmp(e.terminal_handler_pop_rsb_hint);
|
||||||
} else {
|
} else {
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::FastDispatchHint, IR::LocationDescriptor, bool is_single_step) {
|
||||||
if (!e.conf.HasOptimization(OptimizationFlag::FastDispatch) || is_single_step) {
|
if (!e.conf.HasOptimization(OptimizationFlag::FastDispatch) || is_single_step) {
|
||||||
e.code.ReturnFromRunCode();
|
e.code.ReturnFromRunCode();
|
||||||
} else {
|
} else {
|
||||||
e.code.jmp(e.terminal_handler_fast_dispatch_hint);
|
e.code.jmp(e.terminal_handler_fast_dispatch_hint);
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::If terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
switch (terminal.if_) {
|
switch (terminal.if_) {
|
||||||
case IR::Cond::AL:
|
case IR::Cond::AL:
|
||||||
case IR::Cond::NV:
|
case IR::Cond::NV:
|
||||||
e.EmitLeafTerminal(terminal.then_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.then_, initial_location, is_single_step);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Xbyak::Label pass = e.EmitCond(terminal.if_);
|
Xbyak::Label pass = e.EmitCond(terminal.if_);
|
||||||
e.EmitLeafTerminal(terminal.else_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.else_, initial_location, is_single_step);
|
||||||
e.code.L(pass);
|
e.code.L(pass);
|
||||||
e.EmitLeafTerminal(terminal.then_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.then_, initial_location, is_single_step);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::CheckBit terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
Xbyak::Label fail;
|
Xbyak::Label fail;
|
||||||
e.code.cmp(e.code.byte[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, check_bit)], u8(0));
|
e.code.cmp(e.code.byte[rsp + ABI_SHADOW_SPACE + offsetof(StackLayout, check_bit)], u8(0));
|
||||||
e.code.jz(fail);
|
e.code.jz(fail);
|
||||||
e.EmitLeafTerminal(terminal.then_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.then_, initial_location, is_single_step);
|
||||||
e.code.L(fail);
|
e.code.L(fail);
|
||||||
e.EmitLeafTerminal(terminal.else_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.else_, initial_location, is_single_step);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EmitTerminalImpl(A64EmitX64& e, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
void EmitTerminalImpl(A64EmitX64& e, IR::Term::CheckHalt terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||||
e.code.cmp(dword[e.code.ABI_JIT_PTR + offsetof(A64JitState, halt_reason)], 0);
|
e.code.cmp(dword[e.code.ABI_JIT_PTR + offsetof(A64JitState, halt_reason)], 0);
|
||||||
e.code.jne(e.code.GetForceReturnFromRunCodeAddress());
|
e.code.jne(e.code.GetForceReturnFromRunCodeAddress());
|
||||||
e.EmitLeafTerminal(terminal.else_, initial_location, is_single_step);
|
e.EmitTerminal(terminal.else_, initial_location, is_single_step);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
void EmitTerminalImpl(A64EmitX64&, IR::Term::Invalid, IR::LocationDescriptor, bool) {
|
||||||
|
|
||||||
bool A64EmitX64::EmitLeafTerminal(IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept {
|
|
||||||
if (auto const x = std::get_if<IR::Term::ReturnToDispatch>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::PopRSBHint>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::FastDispatchHint>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool A64EmitX64::EmitTerminal(IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept {
|
void A64EmitX64::EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept {
|
||||||
if (auto const x = std::get_if<IR::Term::LeafTerminal>(&terminal))
|
boost::apply_visitor([this, initial_location, is_single_step](auto x) {
|
||||||
return EmitLeafTerminal(*x, initial_location, is_single_step);
|
EmitTerminalImpl(*this, x, initial_location, is_single_step);
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
}, terminal);
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
|
||||||
return EmitTerminalImpl(*this, *x, initial_location, is_single_step);
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void A64EmitX64::EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr) {
|
void A64EmitX64::EmitPatchJg(const IR::LocationDescriptor& target_desc, CodePtr target_code_ptr) {
|
||||||
|
|||||||
@@ -107,8 +107,7 @@ public:
|
|||||||
void EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* inst);
|
void EmitExclusiveWriteMemoryInline(A64EmitContext& ctx, IR::Inst* inst);
|
||||||
|
|
||||||
// Terminal instruction emitters
|
// Terminal instruction emitters
|
||||||
bool EmitLeafTerminal(IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept override;
|
void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept override;
|
||||||
bool EmitTerminal(IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept override;
|
|
||||||
|
|
||||||
// Patching
|
// Patching
|
||||||
void Unpatch(const IR::LocationDescriptor& target_desc) override;
|
void Unpatch(const IR::LocationDescriptor& target_desc) override;
|
||||||
|
|||||||
@@ -111,8 +111,7 @@ public:
|
|||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc);
|
void EmitVerboseDebuggingOutput(RegAlloc& reg_alloc);
|
||||||
#endif
|
#endif
|
||||||
virtual bool EmitLeafTerminal(IR::Term::LeafTerminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept = 0;
|
virtual void EmitTerminal(IR::Terminal terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept = 0;
|
||||||
virtual bool EmitTerminal(IR::Term::Terminal const& terminal, IR::LocationDescriptor initial_location, bool is_single_step) noexcept = 0;
|
|
||||||
|
|
||||||
// Patching
|
// Patching
|
||||||
struct PatchInformation {
|
struct PatchInformation {
|
||||||
|
|||||||
@@ -66,44 +66,43 @@ void Block::Reset(LocationDescriptor location_) noexcept {
|
|||||||
location = location_;
|
location = location_;
|
||||||
end_location = location_;
|
end_location = location_;
|
||||||
cond = Cond::AL;
|
cond = Cond::AL;
|
||||||
terminal = std::monostate{};
|
terminal = Term::Invalid{};
|
||||||
cond_failed_cycle_count = 0;
|
cond_failed_cycle_count = 0;
|
||||||
cycle_count = 0;
|
cycle_count = 0;
|
||||||
ASSERT(instructions.size() == 0);
|
ASSERT(instructions.size() == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string TerminalToString(const Term::Terminal& terminal_variant) noexcept {
|
static std::string TerminalToString(const Terminal& terminal_variant) noexcept {
|
||||||
// struct : boost::static_visitor<std::string> {
|
struct : boost::static_visitor<std::string> {
|
||||||
// std::string operator()(const std::monostate&) const {
|
std::string operator()(const Term::Invalid&) const {
|
||||||
// return "<invalid>";
|
return "<invalid terminal>";
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::ReturnToDispatch&) const {
|
std::string operator()(const Term::ReturnToDispatch&) const {
|
||||||
// return "ReturnToDispatch{}";
|
return "ReturnToDispatch{}";
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::LinkBlock& terminal) const {
|
std::string operator()(const Term::LinkBlock& terminal) const {
|
||||||
// return fmt::format("LinkBlock{{{}}}", terminal.next);
|
return fmt::format("LinkBlock{{{}}}", terminal.next);
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::LinkBlockFast& terminal) const {
|
std::string operator()(const Term::LinkBlockFast& terminal) const {
|
||||||
// return fmt::format("LinkBlockFast{{{}}}", terminal.next);
|
return fmt::format("LinkBlockFast{{{}}}", terminal.next);
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::PopRSBHint&) const {
|
std::string operator()(const Term::PopRSBHint&) const {
|
||||||
// return "PopRSBHint{}";
|
return "PopRSBHint{}";
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::FastDispatchHint&) const {
|
std::string operator()(const Term::FastDispatchHint&) const {
|
||||||
// return "FastDispatchHint{}";
|
return "FastDispatchHint{}";
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::If& terminal) const {
|
std::string operator()(const Term::If& terminal) const {
|
||||||
// return fmt::format("If{{{}, {}, {}}}", A64::CondToString(terminal.if_), TerminalToString(terminal.then_), TerminalToString(terminal.else_));
|
return fmt::format("If{{{}, {}, {}}}", A64::CondToString(terminal.if_), TerminalToString(terminal.then_), TerminalToString(terminal.else_));
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::CheckBit& terminal) const {
|
std::string operator()(const Term::CheckBit& terminal) const {
|
||||||
// return fmt::format("CheckBit{{{}, {}}}", TerminalToString(terminal.then_), TerminalToString(terminal.else_));
|
return fmt::format("CheckBit{{{}, {}}}", TerminalToString(terminal.then_), TerminalToString(terminal.else_));
|
||||||
// }
|
}
|
||||||
// std::string operator()(const Term::CheckHalt& terminal) const {
|
std::string operator()(const Term::CheckHalt& terminal) const {
|
||||||
// return fmt::format("CheckHalt{{{}}}", TerminalToString(terminal.else_));
|
return fmt::format("CheckHalt{{{}}}", TerminalToString(terminal.else_));
|
||||||
// }
|
}
|
||||||
// } visitor;
|
} visitor;
|
||||||
// return boost::apply_visitor(visitor, terminal_variant);
|
return boost::apply_visitor(visitor, terminal_variant);
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string DumpBlock(const IR::Block& block) noexcept {
|
std::string DumpBlock(const IR::Block& block) noexcept {
|
||||||
|
|||||||
@@ -114,22 +114,22 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the terminal instruction for this basic block.
|
/// Gets the terminal instruction for this basic block.
|
||||||
inline Term::Terminal GetTerminal() const noexcept {
|
inline Terminal GetTerminal() const noexcept {
|
||||||
return terminal;
|
return terminal;
|
||||||
}
|
}
|
||||||
/// Sets the terminal instruction for this basic block.
|
/// Sets the terminal instruction for this basic block.
|
||||||
inline void SetTerminal(Term::Terminal term) noexcept {
|
inline void SetTerminal(Terminal term) noexcept {
|
||||||
ASSERT(!HasTerminal() && "Terminal has already been set.");
|
ASSERT(!HasTerminal() && "Terminal has already been set.");
|
||||||
terminal = std::move(term);
|
terminal = std::move(term);
|
||||||
}
|
}
|
||||||
/// Replaces the terminal instruction for this basic block.
|
/// Replaces the terminal instruction for this basic block.
|
||||||
inline void ReplaceTerminal(Term::Terminal term) noexcept {
|
inline void ReplaceTerminal(Terminal term) noexcept {
|
||||||
ASSERT(HasTerminal() && "Terminal has not been set.");
|
ASSERT(HasTerminal() && "Terminal has not been set.");
|
||||||
terminal = std::move(term);
|
terminal = std::move(term);
|
||||||
}
|
}
|
||||||
/// Determines whether or not this basic block has a terminal instruction.
|
/// Determines whether or not this basic block has a terminal instruction.
|
||||||
inline bool HasTerminal() const noexcept {
|
inline bool HasTerminal() const noexcept {
|
||||||
return !std::holds_alternative<std::monostate>(terminal);
|
return terminal.which() != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets a mutable reference to the cycle count for this basic block.
|
/// Gets a mutable reference to the cycle count for this basic block.
|
||||||
@@ -156,7 +156,7 @@ public:
|
|||||||
/// Conditional to pass in order to execute this block
|
/// Conditional to pass in order to execute this block
|
||||||
Cond cond = Cond::AL;
|
Cond cond = Cond::AL;
|
||||||
/// Terminal instruction of this block.
|
/// Terminal instruction of this block.
|
||||||
Term::Terminal terminal = std::monostate{};
|
Terminal terminal = Term::Invalid{};
|
||||||
/// Number of cycles this block takes to execute if the conditional fails.
|
/// Number of cycles this block takes to execute if the conditional fails.
|
||||||
size_t cond_failed_cycle_count = 0;
|
size_t cond_failed_cycle_count = 0;
|
||||||
/// Number of cycles this block takes to execute.
|
/// Number of cycles this block takes to execute.
|
||||||
|
|||||||
@@ -2943,7 +2943,7 @@ public:
|
|||||||
Inst(Opcode::CallHostFunction, Imm64(std::bit_cast<u64>(fn)), arg1, arg2, arg3);
|
Inst(Opcode::CallHostFunction, Imm64(std::bit_cast<u64>(fn)), arg1, arg2, arg3);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetTerm(const Term::Terminal& terminal) {
|
void SetTerm(const Terminal& terminal) {
|
||||||
block.SetTerminal(terminal);
|
block.SetTerminal(terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <variant>
|
#include <boost/variant.hpp>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
#include "dynarmic/ir/cond.h"
|
#include "dynarmic/ir/cond.h"
|
||||||
@@ -17,89 +17,106 @@
|
|||||||
namespace Dynarmic::IR {
|
namespace Dynarmic::IR {
|
||||||
namespace Term {
|
namespace Term {
|
||||||
|
|
||||||
/// This terminal instruction returns control to the dispatcher.
|
struct Invalid {};
|
||||||
/// The dispatcher will use the current cpu state to determine what comes next.
|
|
||||||
|
/**
|
||||||
|
* This terminal instruction returns control to the dispatcher.
|
||||||
|
* The dispatcher will use the current cpu state to determine what comes next.
|
||||||
|
*/
|
||||||
struct ReturnToDispatch {};
|
struct ReturnToDispatch {};
|
||||||
|
|
||||||
/// This terminal instruction jumps to the basic block described by `next` if we have enough
|
/**
|
||||||
/// cycles remaining. If we do not have enough cycles remaining, we return to the
|
* This terminal instruction jumps to the basic block described by `next` if we have enough
|
||||||
/// dispatcher, which will return control to the host.
|
* cycles remaining. If we do not have enough cycles remaining, we return to the
|
||||||
|
* dispatcher, which will return control to the host.
|
||||||
|
*/
|
||||||
struct LinkBlock {
|
struct LinkBlock {
|
||||||
explicit LinkBlock(const LocationDescriptor& next_) : next(next_) {}
|
explicit LinkBlock(const LocationDescriptor& next_)
|
||||||
|
: next(next_) {}
|
||||||
LocationDescriptor next; ///< Location descriptor for next block.
|
LocationDescriptor next; ///< Location descriptor for next block.
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This terminal instruction jumps to the basic block described by `next` unconditionally.
|
/**
|
||||||
/// This is an optimization and MUST only be emitted when this is guaranteed not to result
|
* This terminal instruction jumps to the basic block described by `next` unconditionally.
|
||||||
/// in hanging, even in the face of other optimizations. (In practice, this means that only
|
* This is an optimization and MUST only be emitted when this is guaranteed not to result
|
||||||
/// forward jumps to short-ish blocks would use this instruction.)
|
* in hanging, even in the face of other optimizations. (In practice, this means that only
|
||||||
/// A backend that doesn't support this optimization may choose to implement this exactly
|
* forward jumps to short-ish blocks would use this instruction.)
|
||||||
/// as LinkBlock.
|
* A backend that doesn't support this optimization may choose to implement this exactly
|
||||||
|
* as LinkBlock.
|
||||||
|
*/
|
||||||
struct LinkBlockFast {
|
struct LinkBlockFast {
|
||||||
explicit LinkBlockFast(const LocationDescriptor& next_) : next(next_) {}
|
explicit LinkBlockFast(const LocationDescriptor& next_)
|
||||||
|
: next(next_) {}
|
||||||
LocationDescriptor next; ///< Location descriptor for next block.
|
LocationDescriptor next; ///< Location descriptor for next block.
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This terminal instruction checks the top of the Return Stack Buffer against the current
|
/**
|
||||||
/// location descriptor. If RSB lookup fails, control is returned to the dispatcher.
|
* This terminal instruction checks the top of the Return Stack Buffer against the current
|
||||||
/// This is an optimization for faster function calls. A backend that doesn't support
|
* location descriptor. If RSB lookup fails, control is returned to the dispatcher.
|
||||||
/// this optimization or doesn't have a RSB may choose to implement this exactly as
|
* This is an optimization for faster function calls. A backend that doesn't support
|
||||||
/// ReturnToDispatch.
|
* this optimization or doesn't have a RSB may choose to implement this exactly as
|
||||||
|
* ReturnToDispatch.
|
||||||
|
*/
|
||||||
struct PopRSBHint {};
|
struct PopRSBHint {};
|
||||||
|
|
||||||
/// This terminal instruction performs a lookup of the current location descriptor in the
|
/**
|
||||||
/// fast dispatch lookup table. A backend that doesn't support this optimization may choose
|
* This terminal instruction performs a lookup of the current location descriptor in the
|
||||||
/// to implement this exactly as ReturnToDispatch.
|
* fast dispatch lookup table. A backend that doesn't support this optimization may choose
|
||||||
|
* to implement this exactly as ReturnToDispatch.
|
||||||
|
*/
|
||||||
struct FastDispatchHint {};
|
struct FastDispatchHint {};
|
||||||
|
|
||||||
struct If;
|
struct If;
|
||||||
struct CheckBit;
|
struct CheckBit;
|
||||||
struct CheckHalt;
|
struct CheckHalt;
|
||||||
|
/// A Terminal is the terminal instruction in a MicroBlock.
|
||||||
/// Non recursive kind of terminal
|
using Terminal = boost::variant<
|
||||||
using LeafTerminal = std::variant<
|
Invalid,
|
||||||
std::monostate,
|
|
||||||
ReturnToDispatch,
|
ReturnToDispatch,
|
||||||
LinkBlock,
|
LinkBlock,
|
||||||
LinkBlockFast,
|
LinkBlockFast,
|
||||||
PopRSBHint,
|
PopRSBHint,
|
||||||
FastDispatchHint
|
FastDispatchHint,
|
||||||
>;
|
boost::recursive_wrapper<If>,
|
||||||
|
boost::recursive_wrapper<CheckBit>,
|
||||||
|
boost::recursive_wrapper<CheckHalt>>;
|
||||||
|
|
||||||
/// A Terminal is the terminal instruction in a MicroBlock.
|
/**
|
||||||
using Terminal = std::variant<
|
* This terminal instruction conditionally executes one terminal or another depending
|
||||||
std::monostate,
|
* on the run-time state of the ARM flags.
|
||||||
LeafTerminal,
|
*/
|
||||||
If,
|
|
||||||
CheckBit,
|
|
||||||
CheckHalt
|
|
||||||
>;
|
|
||||||
|
|
||||||
/// This terminal instruction conditionally executes one terminal or another depending
|
|
||||||
/// on the run-time state of the ARM flags.
|
|
||||||
struct If {
|
struct If {
|
||||||
explicit If(Cond if_, LeafTerminal then_, LeafTerminal else_) : if_(if_), then_(std::move(then_)), else_(std::move(else_)) {}
|
If(Cond if_, Terminal then_, Terminal else_)
|
||||||
|
: if_(if_), then_(std::move(then_)), else_(std::move(else_)) {}
|
||||||
Cond if_;
|
Cond if_;
|
||||||
LeafTerminal then_;
|
Terminal then_;
|
||||||
LeafTerminal else_;
|
Terminal else_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This terminal instruction conditionally executes one terminal or another depending
|
/**
|
||||||
/// on the run-time state of the check bit.
|
* This terminal instruction conditionally executes one terminal or another depending
|
||||||
/// then_ is executed if the check bit is non-zero, otherwise else_ is executed.
|
* on the run-time state of the check bit.
|
||||||
|
* then_ is executed if the check bit is non-zero, otherwise else_ is executed.
|
||||||
|
*/
|
||||||
struct CheckBit {
|
struct CheckBit {
|
||||||
explicit CheckBit(LeafTerminal then_, LeafTerminal else_) : then_(std::move(then_)), else_(std::move(else_)) {}
|
CheckBit(Terminal then_, Terminal else_)
|
||||||
LeafTerminal then_;
|
: then_(std::move(then_)), else_(std::move(else_)) {}
|
||||||
LeafTerminal else_;
|
Terminal then_;
|
||||||
|
Terminal else_;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This terminal instruction checks if a halt was requested. If it wasn't, else_ is
|
/**
|
||||||
/// executed.
|
* This terminal instruction checks if a halt was requested. If it wasn't, else_ is
|
||||||
|
* executed.
|
||||||
|
*/
|
||||||
struct CheckHalt {
|
struct CheckHalt {
|
||||||
explicit CheckHalt(LeafTerminal else_) : else_(std::move(else_)) {}
|
explicit CheckHalt(Terminal else_)
|
||||||
LeafTerminal else_;
|
: else_(std::move(else_)) {}
|
||||||
|
Terminal else_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Term
|
} // namespace Term
|
||||||
|
|
||||||
|
using Term::Terminal;
|
||||||
|
|
||||||
} // namespace Dynarmic::IR
|
} // namespace Dynarmic::IR
|
||||||
|
|||||||
@@ -43,20 +43,32 @@ namespace {
|
|||||||
using namespace Dynarmic;
|
using namespace Dynarmic;
|
||||||
|
|
||||||
template<typename Fn>
|
template<typename Fn>
|
||||||
bool AnyLocationDescriptorForTerminalHas(IR::Term::Terminal terminal, Fn fn) {
|
bool AnyLocationDescriptorForTerminalHas(IR::Terminal terminal, Fn fn) {
|
||||||
if (auto const e = std::get_if<IR::Term::LeafTerminal>(&terminal)) {
|
return boost::apply_visitor([&](auto t) -> bool {
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlock>(e))
|
using T = std::decay_t<decltype(t)>;
|
||||||
return fn(x->next);
|
if constexpr (std::is_same_v<T, IR::Term::Invalid>) {
|
||||||
if (auto const x = std::get_if<IR::Term::LinkBlockFast>(e))
|
return false;
|
||||||
return fn(x->next);
|
} else if constexpr (std::is_same_v<T, IR::Term::ReturnToDispatch>) {
|
||||||
}
|
return false;
|
||||||
if (auto const x = std::get_if<IR::Term::If>(&terminal))
|
} else if constexpr (std::is_same_v<T, IR::Term::LinkBlock>) {
|
||||||
return AnyLocationDescriptorForTerminalHas(x->then_, fn) || AnyLocationDescriptorForTerminalHas(x->else_, fn);
|
return fn(t.next);
|
||||||
if (auto const x = std::get_if<IR::Term::CheckBit>(&terminal))
|
} else if constexpr (std::is_same_v<T, IR::Term::LinkBlockFast>) {
|
||||||
return AnyLocationDescriptorForTerminalHas(x->then_, fn) || AnyLocationDescriptorForTerminalHas(x->else_, fn);
|
return fn(t.next);
|
||||||
if (auto const x = std::get_if<IR::Term::CheckHalt>(&terminal))
|
} else if constexpr (std::is_same_v<T, IR::Term::PopRSBHint>) {
|
||||||
return AnyLocationDescriptorForTerminalHas(x->else_, fn);
|
return false;
|
||||||
return false;
|
} else if constexpr (std::is_same_v<T, IR::Term::FastDispatchHint>) {
|
||||||
|
return false;
|
||||||
|
} else if constexpr (std::is_same_v<T, IR::Term::If>) {
|
||||||
|
return AnyLocationDescriptorForTerminalHas(t.then_, fn) || AnyLocationDescriptorForTerminalHas(t.else_, fn);
|
||||||
|
} else if constexpr (std::is_same_v<T, IR::Term::CheckBit>) {
|
||||||
|
return AnyLocationDescriptorForTerminalHas(t.then_, fn) || AnyLocationDescriptorForTerminalHas(t.else_, fn);
|
||||||
|
} else if constexpr (std::is_same_v<T, IR::Term::CheckHalt>) {
|
||||||
|
return AnyLocationDescriptorForTerminalHas(t.else_, fn);
|
||||||
|
} else {
|
||||||
|
ASSERT(false && "Invalid terminal type");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}, terminal);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ShouldTestInst(u32 instruction, u32 pc, bool is_thumb, bool is_last_inst, A32::ITState it_state = {}) {
|
bool ShouldTestInst(u32 instruction, u32 pc, bool is_thumb, bool is_last_inst, A32::ITState it_state = {}) {
|
||||||
|
|||||||
@@ -224,7 +224,7 @@ void ExecuteA32Instruction(u32 instruction) {
|
|||||||
fmt::print("value: ");
|
fmt::print("value: ");
|
||||||
if (const auto value = get_value()) {
|
if (const auto value = get_value()) {
|
||||||
*(iter->second) = *value;
|
*(iter->second) = *value;
|
||||||
fmt::print("> {} = {:#08x}\n", reg_name, *value);
|
fmt::print("> {} = 0x{:08x}\n", reg_name, *value);
|
||||||
}
|
}
|
||||||
} else if (reg_name.starts_with("m")) {
|
} else if (reg_name.starts_with("m")) {
|
||||||
fmt::print("address: ");
|
fmt::print("address: ");
|
||||||
@@ -232,7 +232,7 @@ void ExecuteA32Instruction(u32 instruction) {
|
|||||||
fmt::print("value: ");
|
fmt::print("value: ");
|
||||||
if (const auto value = get_value()) {
|
if (const auto value = get_value()) {
|
||||||
env.MemoryWrite32(*address, *value);
|
env.MemoryWrite32(*address, *value);
|
||||||
fmt::print("> mem[{:#08x}] = {:#08x}\n", *address, *value);
|
fmt::print("> mem[0x{:08x}] = 0x{:08x}\n", *address, *value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (reg_name == "exit" || reg_name == "end" || reg_name.starts_with("q")) {
|
} else if (reg_name == "exit" || reg_name == "end" || reg_name.starts_with("q")) {
|
||||||
|
|||||||
@@ -100,7 +100,6 @@ void EmulatedConsole::ReloadInput() {
|
|||||||
motion.gyro = emulated_motion.GetGyroscope();
|
motion.gyro = emulated_motion.GetGyroscope();
|
||||||
motion.rotation = emulated_motion.GetRotations();
|
motion.rotation = emulated_motion.GetRotations();
|
||||||
motion.orientation = emulated_motion.GetOrientation();
|
motion.orientation = emulated_motion.GetOrientation();
|
||||||
motion.quaternion = emulated_motion.GetQuaternion();
|
|
||||||
motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity);
|
motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity);
|
||||||
|
|
||||||
// Unique index for identifying touch device source
|
// Unique index for identifying touch device source
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
@@ -72,6 +72,15 @@ Mouse::Mouse(std::string input_engine_) : InputEngine(std::move(input_engine_))
|
|||||||
wheel_position = {};
|
wheel_position = {};
|
||||||
last_mouse_change = {};
|
last_mouse_change = {};
|
||||||
last_motion_change = {};
|
last_motion_change = {};
|
||||||
|
|
||||||
|
update_thread = std::jthread([this](std::stop_token stop_token) {
|
||||||
|
Common::SetCurrentThreadName("Mouse");
|
||||||
|
while (!stop_token.stop_requested()) {
|
||||||
|
UpdateStickInput();
|
||||||
|
UpdateMotionInput();
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(update_time));
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::UpdateStickInput() {
|
void Mouse::UpdateStickInput() {
|
||||||
@@ -176,11 +185,6 @@ void Mouse::Move(int x, int y, int center_x, int center_y) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mouse::NotifyChanged() {
|
|
||||||
UpdateStickInput();
|
|
||||||
UpdateMotionInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
|
void Mouse::MouseMove(f32 touch_x, f32 touch_y) {
|
||||||
SetAxis(real_mouse_identifier, mouse_axis_x, touch_x);
|
SetAxis(real_mouse_identifier, mouse_axis_x, touch_x);
|
||||||
SetAxis(real_mouse_identifier, mouse_axis_y, touch_y);
|
SetAxis(real_mouse_identifier, mouse_axis_y, touch_y);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
@@ -93,9 +93,6 @@ public:
|
|||||||
|
|
||||||
void ReleaseAllButtons();
|
void ReleaseAllButtons();
|
||||||
|
|
||||||
/// @brief Notifies we changed something about the mouse state and we must update
|
|
||||||
void NotifyChanged();
|
|
||||||
|
|
||||||
std::vector<Common::ParamPackage> GetInputDevices() const override;
|
std::vector<Common::ParamPackage> GetInputDevices() const override;
|
||||||
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
|
AnalogMapping GetAnalogMappingForDevice(const Common::ParamPackage& params) override;
|
||||||
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
|
Common::Input::ButtonNames GetUIName(const Common::ParamPackage& params) const override;
|
||||||
@@ -113,6 +110,7 @@ private:
|
|||||||
Common::Vec3<float> last_motion_change;
|
Common::Vec3<float> last_motion_change;
|
||||||
Common::Vec2<int> wheel_position;
|
Common::Vec2<int> wheel_position;
|
||||||
bool button_pressed = false;
|
bool button_pressed = false;
|
||||||
|
std::jthread update_thread;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace InputCommon
|
} // namespace InputCommon
|
||||||
|
|||||||
@@ -136,7 +136,7 @@ public:
|
|||||||
const std::array<QString, 4> row_data{{
|
const std::array<QString, 4> row_data{{
|
||||||
QString::fromStdString(filename),
|
QString::fromStdString(filename),
|
||||||
data(FileTypeRole).toString(),
|
data(FileTypeRole).toString(),
|
||||||
QString::fromStdString(fmt::format("{:#016x}", data(ProgramIdRole).toULongLong())),
|
QString::fromStdString(fmt::format("0x{:016X}", data(ProgramIdRole).toULongLong())),
|
||||||
data(TitleRole).toString(),
|
data(TitleRole).toString(),
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
@@ -46,7 +46,7 @@ Opcode Decode(u64 insn) {
|
|||||||
return Opcode::name;
|
return Opcode::name;
|
||||||
#include "maxwell.inc"
|
#include "maxwell.inc"
|
||||||
#undef INST
|
#undef INST
|
||||||
ASSERT_MSG(false, "Invalid insn {:#016x}", insn);
|
ASSERT_MSG(false, "Invalid insn 0x{:016x}", insn);
|
||||||
return Opcode::NOP;
|
return Opcode::NOP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user