mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-11-02 20:13:58 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 060026dc2d | |||
| 92f54a034a | |||
| 7a6d055094 | |||
| c6fa5c1f77 | |||
| 2c40328a23 | |||
| 41b6807f12 | |||
| 2bec66c092 |
Vendored
+667
-653
File diff suppressed because it is too large
Load Diff
Vendored
+630
-620
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+631
-621
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+631
-621
File diff suppressed because it is too large
Load Diff
Vendored
+635
-625
File diff suppressed because it is too large
Load Diff
Vendored
+630
-620
File diff suppressed because it is too large
Load Diff
Vendored
+629
-619
File diff suppressed because it is too large
Load Diff
Vendored
+629
-619
File diff suppressed because it is too large
Load Diff
Vendored
+631
-621
File diff suppressed because it is too large
Load Diff
Vendored
+639
-628
File diff suppressed because it is too large
Load Diff
Vendored
+688
-673
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+631
-621
File diff suppressed because it is too large
Load Diff
Vendored
+630
-620
File diff suppressed because it is too large
Load Diff
Vendored
+629
-619
File diff suppressed because it is too large
Load Diff
Vendored
+631
-621
File diff suppressed because it is too large
Load Diff
Vendored
+632
-622
File diff suppressed because it is too large
Load Diff
Vendored
+630
-620
File diff suppressed because it is too large
Load Diff
Vendored
+631
-621
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+634
-624
File diff suppressed because it is too large
Load Diff
Vendored
+665
-650
File diff suppressed because it is too large
Load Diff
Vendored
+630
-620
File diff suppressed because it is too large
Load Diff
Vendored
+3
-4
@@ -33,10 +33,9 @@ Eden by default will be cloned into:
|
|||||||
## Building with Terminal
|
## Building with Terminal
|
||||||
|
|
||||||
1. Download the SDK and NDK from Android Studio.
|
1. Download the SDK and NDK from Android Studio.
|
||||||
2. Navigate to SDK and NDK paths.
|
2. Navigate to SDK path.
|
||||||
3. Then set ANDROID_SDK_ROOT and ANDROID_NDK_ROOT in terminal via
|
3. Then set ANDROID_HOME in terminal via
|
||||||
`export ANDROID_SDK_ROOT=path/to/sdk`
|
`export ANDROID_HOME=path/to/sdk`
|
||||||
`export ANDROID_NDK_ROOT=path/to/ndk`.
|
|
||||||
4. Navigate to `eden/src/android`.
|
4. Navigate to `eden/src/android`.
|
||||||
5. Then Build with `./gradlew assembleRelWithDebInfo`.
|
5. Then Build with `./gradlew assembleRelWithDebInfo`.
|
||||||
6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`.
|
6. To build the optimised build use `./gradlew assembleGenshinSpoofRelWithDebInfo`.
|
||||||
|
|||||||
@@ -79,9 +79,8 @@ class DriverFetcherFragment : Fragment() {
|
|||||||
IntRange(100, 599) to "Unsupported",
|
IntRange(100, 599) to "Unsupported",
|
||||||
IntRange(600, 639) to "Mr. Purple EOL-24.3.4",
|
IntRange(600, 639) to "Mr. Purple EOL-24.3.4",
|
||||||
IntRange(640, 699) to "Mr. Purple T19",
|
IntRange(640, 699) to "Mr. Purple T19",
|
||||||
IntRange(700, 710) to "KIMCHI 25.2.0_r5",
|
IntRange(700, 710) to "Mr. Purple T29",
|
||||||
IntRange(711, 799) to "Mr. Purple T23",
|
IntRange(711, 899) to "Mr. Purple T30",
|
||||||
IntRange(800, 899) to "GameHub Adreno 8xx",
|
|
||||||
IntRange(900, Int.MAX_VALUE) to "Unsupported"
|
IntRange(900, Int.MAX_VALUE) to "Unsupported"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -351,7 +351,7 @@
|
|||||||
<string name="frame_generation_unsupported">غير مدعوم (لا يتوفر نموذج ذاكرة Vulkan أو float16)</string>
|
<string name="frame_generation_unsupported">غير مدعوم (لا يتوفر نموذج ذاكرة Vulkan أو float16)</string>
|
||||||
<string name="lossless_scaling">Lossless Scaling</string>
|
<string name="lossless_scaling">Lossless Scaling</string>
|
||||||
<string name="lossless_scaling_description">قم بتوفير نسختك الخاصة من ملف Lossless.dll لتفعيل توليد الإطارات</string>
|
<string name="lossless_scaling_description">قم بتوفير نسختك الخاصة من ملف Lossless.dll لتفعيل توليد الإطارات</string>
|
||||||
<string name="lossless_scaling_installed">مثبت</string>
|
<string name="lossless_scaling_installed">تم التثبيت</string>
|
||||||
<string name="lossless_scaling_not_installed">غير مثبت</string>
|
<string name="lossless_scaling_not_installed">غير مثبت</string>
|
||||||
<string name="lossless_scaling_replace">استبدل</string>
|
<string name="lossless_scaling_replace">استبدل</string>
|
||||||
<string name="lossless_scaling_remove">إزالة</string>
|
<string name="lossless_scaling_remove">إزالة</string>
|
||||||
@@ -501,9 +501,9 @@
|
|||||||
<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">السرعة الفائقة</string>
|
||||||
<string name="turbo_speed_limit_description">عند تفعيل وضع التيربو، سيتم تشغيل المحاكاة بهذه السرعة.</string>
|
<string name="turbo_speed_limit_description">عند تفعيل وضع التيربو، سيتم تشغيل المحاكاة بهذه السرعة.</string>
|
||||||
<string name="slow_speed_limit">سرعة بطيئة</string>
|
<string name="slow_speed_limit">السرعة البطيئة</string>
|
||||||
<string name="slow_speed_limit_description">عند تفعيل الوضع البطيء، سيتم تشغيل المحاكاة بهذه السرعة.</string>
|
<string name="slow_speed_limit_description">عند تفعيل الوضع البطيء، سيتم تشغيل المحاكاة بهذه السرعة.</string>
|
||||||
<string name="cpu_backend">خلفية وحدة المعالجة المركزية</string>
|
<string name="cpu_backend">خلفية وحدة المعالجة المركزية</string>
|
||||||
<string name="cpu_accuracy">دقة وحدة المعالجة المركزية</string>
|
<string name="cpu_accuracy">دقة وحدة المعالجة المركزية</string>
|
||||||
@@ -514,7 +514,7 @@
|
|||||||
|
|
||||||
<!-- 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>
|
||||||
@@ -543,7 +543,7 @@
|
|||||||
<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">VSync وضع</string>
|
<string name="renderer_vsync">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">حدة FSR/SGSR</string>
|
||||||
@@ -588,7 +588,7 @@
|
|||||||
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
|
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
|
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
|
||||||
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
|
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
|
||||||
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno A6XX - A7XX/ Turnip)، ويزيل التوهج في Burnout. تحذير: قد يسبب تشوهات رسومية في ألعاب أخرى.</string>
|
<string name="fix_bloom_effects_description">يزيل تأثير التوهج في لعبة Burnout.</string>
|
||||||
<string name="emulate_bgr565">محاكاة BGR565</string>
|
<string name="emulate_bgr565">محاكاة BGR565</string>
|
||||||
<string name="emulate_bgr565_description">يُصلح مشاكل انعكاس الألوان في الألعاب أو ظهور تشوهات غريبة أو ظلال غريبة.</string>
|
<string name="emulate_bgr565_description">يُصلح مشاكل انعكاس الألوان في الألعاب أو ظهور تشوهات غريبة أو ظلال غريبة.</string>
|
||||||
<string name="rescale_hack">تفعيل ميزة إعادة التحجيم القديمة</string>
|
<string name="rescale_hack">تفعيل ميزة إعادة التحجيم القديمة</string>
|
||||||
@@ -694,7 +694,7 @@
|
|||||||
<string name="control_stick">عصا التحكم</string>
|
<string name="control_stick">عصا التحكم</string>
|
||||||
<string name="right_stick">العصا اليمنى</string>
|
<string name="right_stick">العصا اليمنى</string>
|
||||||
<string name="c_stick">عصا-C</string>
|
<string name="c_stick">عصا-C</string>
|
||||||
<string name="pressed">مضغوط</string>
|
<string name="pressed">ضغط العصا</string>
|
||||||
<string name="range">النطاق</string>
|
<string name="range">النطاق</string>
|
||||||
<string name="deadzone">المنطقة الميتة</string>
|
<string name="deadzone">المنطقة الميتة</string>
|
||||||
<string name="modifier">معدل</string>
|
<string name="modifier">معدل</string>
|
||||||
@@ -821,10 +821,16 @@
|
|||||||
<!-- Preferences Screen -->
|
<!-- Preferences Screen -->
|
||||||
<string name="preferences_settings">الإعدادات</string>
|
<string name="preferences_settings">الإعدادات</string>
|
||||||
<string name="preferences_system">النظام</string>
|
<string name="preferences_system">النظام</string>
|
||||||
<string name="preferences_system_description">وضع الإرساء، المنطقة، اللغة</string>
|
<string name="preferences_system_description">وضع المنصة، المنطقة، اللغة</string>
|
||||||
<string name="preferences_graphics">الرسومات</string>
|
<string name="preferences_graphics">الرسومات</string>
|
||||||
<string name="preferences_graphics_description">مستوى دقة المحاكاة، الدقة، ذاكرة التخزين المؤقتة للتظليل</string>
|
<string name="preferences_graphics_description">مستوى دقة المحاكاة، الدقة، ذاكرة التخزين المؤقتة للتظليل</string>
|
||||||
<string name="quick_settings">الإعدادات السريعة</string>
|
<string name="quick_settings">الإعدادات السريعة</string>
|
||||||
|
<string name="cheats">رموز الغش</string>
|
||||||
|
<string name="enable_all_cheats">تفعيل جميع رموز الغش</string>
|
||||||
|
<string name="disable_all_cheats">تعطيل جميع رموز الغش</string>
|
||||||
|
<string name="unnamed_cheat">رمز الغش بدون اسم</string>
|
||||||
|
<string name="enable_cheats_by_default">تفعيل رموز الغش بشكل افتراضي</string>
|
||||||
|
<string name="enable_cheats_by_default_description">تفعيل رموز الغش الاعتيادية عند بدء اللعبة</string>
|
||||||
<string name="enable_quick_settings">تفعيل الإعدادات السريعة</string>
|
<string name="enable_quick_settings">تفعيل الإعدادات السريعة</string>
|
||||||
<string name="enable_quick_settings_description">السماح بالوصول إلى قائمة الإعدادات السريعة عن طريق التمرير و زر القائمة</string>
|
<string name="enable_quick_settings_description">السماح بالوصول إلى قائمة الإعدادات السريعة عن طريق التمرير و زر القائمة</string>
|
||||||
<string name="preferences_audio">الصوت</string>
|
<string name="preferences_audio">الصوت</string>
|
||||||
@@ -869,12 +875,12 @@
|
|||||||
<string name="copy_details">نسخ التفاصيل</string>
|
<string name="copy_details">نسخ التفاصيل</string>
|
||||||
<string name="add_ons">الإضافات</string>
|
<string name="add_ons">الإضافات</string>
|
||||||
<string name="add_ons_description">تفعيل/تعطيل التعديلات، التحديثات، المحتوى القابل للتنزيل</string>
|
<string name="add_ons_description">تفعيل/تعطيل التعديلات، التحديثات، المحتوى القابل للتنزيل</string>
|
||||||
<string name="playtime">زمن اللعب:</string>
|
<string name="playtime">وقت اللعب:</string>
|
||||||
<string name="reset_playtime">مسح زمن اللعب</string>
|
<string name="reset_playtime">مسح وقت اللعب</string>
|
||||||
<string name="reset_playtime_description">إعادة تعيين زمن اللعب للعبة الحالية إلى 0 ثانية</string>
|
<string name="reset_playtime_description">إعادة تعيين وقت لعب اللعبة الحالية إلى 0 ثانية</string>
|
||||||
<string name="reset_playtime_warning_description">سيؤدي هذا إلى مسح بيانات زمن اللعب الحالية للعبة. هل أنت متأكد؟</string>
|
<string name="reset_playtime_warning_description">سيؤدي هذا إلى مسح بيانات وقت اللعب للعبة الحالية. هل أنت متأكد؟</string>
|
||||||
<string name="playtime_reset_successfully">تمت إعادة تعيين زمن اللعب</string>
|
<string name="playtime_reset_successfully">تمت إعادة تعيين وقت اللعب</string>
|
||||||
<string name="edit_playtime">تعديل زمن اللعب</string>
|
<string name="edit_playtime">تعديل وقت اللعب</string>
|
||||||
<string name="hours">ساعات</string>
|
<string name="hours">ساعات</string>
|
||||||
<string name="minutes">دقائق</string>
|
<string name="minutes">دقائق</string>
|
||||||
<string name="hours_abbr">س</string>
|
<string name="hours_abbr">س</string>
|
||||||
@@ -883,7 +889,7 @@
|
|||||||
<string name="hours_must_be_between_0_and_9999">يجب أن تكون الساعات بين 0 و 9999</string>
|
<string name="hours_must_be_between_0_and_9999">يجب أن تكون الساعات بين 0 و 9999</string>
|
||||||
<string name="minutes_must_be_between_0_and_59">يجب أن تكون الدقائق بين 0 و 59</string>
|
<string name="minutes_must_be_between_0_and_59">يجب أن تكون الدقائق بين 0 و 59</string>
|
||||||
<string name="seconds_must_be_between_0_and_59">يجب أن تكون الثواني بين 0 و 59</string>
|
<string name="seconds_must_be_between_0_and_59">يجب أن تكون الثواني بين 0 و 59</string>
|
||||||
<string name="playtime_updated_successfully">تم تحديث زمن اللعب بنجاح</string>
|
<string name="playtime_updated_successfully">تم تحديث وقت اللعب بنجاح</string>
|
||||||
<string name="clear_shader_cache">مسح ذاكرة التخزين المؤقتة للتظليل</string>
|
<string name="clear_shader_cache">مسح ذاكرة التخزين المؤقتة للتظليل</string>
|
||||||
<string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string>
|
<string name="clear_shader_cache_description">يزيل جميع التظليلات التي تم إنشاؤها أثناء لعب هذه اللعبة</string>
|
||||||
<string name="clear_shader_cache_warning_description">ستواجه المزيد من التقطع مع إعادة إنشاء ذاكرة التخزين المؤقتة للتظلل</string>
|
<string name="clear_shader_cache_warning_description">ستواجه المزيد من التقطع مع إعادة إنشاء ذاكرة التخزين المؤقتة للتظلل</string>
|
||||||
|
|||||||
@@ -531,7 +531,6 @@
|
|||||||
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
|
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
|
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
|
||||||
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
|
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
|
||||||
<string name="fix_bloom_effects_description">Reduce el efecto de resplandor en LA/EOW (Adreno A6XX - A7XX/ Turnip), elimina el resplandor en Burnout. Advertencia: puede causar artefactos gráficos en otros juegos.</string>
|
|
||||||
<string name="emulate_bgr565">Emular BGR565</string>
|
<string name="emulate_bgr565">Emular BGR565</string>
|
||||||
<string name="emulate_bgr565_description">Soluciona problemas con colores invertidos en juegos, artefactos o sombras extrañas.</string>
|
<string name="emulate_bgr565_description">Soluciona problemas con colores invertidos en juegos, artefactos o sombras extrañas.</string>
|
||||||
<string name="rescale_hack">Activar la pasada de reescalado heredada</string>
|
<string name="rescale_hack">Activar la pasada de reescalado heredada</string>
|
||||||
|
|||||||
@@ -577,7 +577,6 @@
|
|||||||
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
|
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
|
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
|
||||||
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
|
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
|
||||||
<string name="fix_bloom_effects_description">Частично убирает размытие в LA/EOW (Adreno A6XX - A7XX/ Turnip), полностью отключает его в Burnout. Внимание: может вызывать графические артефакты в других играх.</string>
|
|
||||||
<string name="emulate_bgr565">Эмулировать BGR565</string>
|
<string name="emulate_bgr565">Эмулировать BGR565</string>
|
||||||
<string name="emulate_bgr565_description">Исправляет проблемы с инвертированными цветами в играх, а также со странными артефактами или некорректными тенями.</string>
|
<string name="emulate_bgr565_description">Исправляет проблемы с инвертированными цветами в играх, а также со странными артефактами или некорректными тенями.</string>
|
||||||
<string name="rescale_hack">Включить старый метод изменения разрешения</string>
|
<string name="rescale_hack">Включить старый метод изменения разрешения</string>
|
||||||
|
|||||||
@@ -493,7 +493,6 @@
|
|||||||
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
|
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
|
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
|
||||||
<string name="fix_bloom_effects">Виправити ефекти світіння</string>
|
<string name="fix_bloom_effects">Виправити ефекти світіння</string>
|
||||||
<string name="fix_bloom_effects_description">Зменшує розмиття світіння в LA/EOW (Adreno A6XX–A7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
|
|
||||||
<string name="emulate_bgr565">Емулювати BGR565</string>
|
<string name="emulate_bgr565">Емулювати BGR565</string>
|
||||||
<string name="emulate_bgr565_description">Виправляє проблеми з інвертованими кольорами в іграх або дивними артефактами чи тінями.</string>
|
<string name="emulate_bgr565_description">Виправляє проблеми з інвертованими кольорами в іграх або дивними артефактами чи тінями.</string>
|
||||||
<string name="rescale_hack">Увімкнути застаріле масштабування</string>
|
<string name="rescale_hack">Увімкнути застаріле масштабування</string>
|
||||||
|
|||||||
@@ -578,7 +578,7 @@
|
|||||||
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
|
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">在更新内存时跳过某些 CPU 端的缓存失效操作,从而降低 CPU 占用率并提升性能。可能会在某些游戏中引发故障点或崩溃。</string>
|
<string name="skip_cpu_inner_invalidation_description">在更新内存时跳过某些 CPU 端的缓存失效操作,从而降低 CPU 占用率并提升性能。可能会在某些游戏中引发故障点或崩溃。</string>
|
||||||
<string name="fix_bloom_effects">修复 Bloom 效果</string>
|
<string name="fix_bloom_effects">修复 Bloom 效果</string>
|
||||||
<string name="fix_bloom_effects_description">减少《智慧的再现》和《众神的三角力量2》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
|
<string name="fix_bloom_effects_description">去除《火爆狂飙》中的泛光特效。</string>
|
||||||
<string name="emulate_bgr565">模拟 BGR565</string>
|
<string name="emulate_bgr565">模拟 BGR565</string>
|
||||||
<string name="emulate_bgr565_description">修复游戏中的颜色反转或是异常的画面瑕疵或阴影问题</string>
|
<string name="emulate_bgr565_description">修复游戏中的颜色反转或是异常的画面瑕疵或阴影问题</string>
|
||||||
<string name="rescale_hack">启用旧版缩放处理</string>
|
<string name="rescale_hack">启用旧版缩放处理</string>
|
||||||
@@ -815,6 +815,12 @@
|
|||||||
<string name="preferences_graphics">图形</string>
|
<string name="preferences_graphics">图形</string>
|
||||||
<string name="preferences_graphics_description">精度等级、分辨率及着色器缓存</string>
|
<string name="preferences_graphics_description">精度等级、分辨率及着色器缓存</string>
|
||||||
<string name="quick_settings">快速设置</string>
|
<string name="quick_settings">快速设置</string>
|
||||||
|
<string name="cheats">作弊</string>
|
||||||
|
<string name="enable_all_cheats">开启所有作弊</string>
|
||||||
|
<string name="disable_all_cheats">关闭所有作弊</string>
|
||||||
|
<string name="unnamed_cheat">未命名的作弊</string>
|
||||||
|
<string name="enable_cheats_by_default">默认开启作弊</string>
|
||||||
|
<string name="enable_cheats_by_default_description">在游戏启动时启用常规作弊</string>
|
||||||
<string name="enable_quick_settings">启用快速设置</string>
|
<string name="enable_quick_settings">启用快速设置</string>
|
||||||
<string name="enable_quick_settings_description">允许通过滑动和菜单按钮访问快速设置菜单</string>
|
<string name="enable_quick_settings_description">允许通过滑动和菜单按钮访问快速设置菜单</string>
|
||||||
<string name="preferences_audio">声音</string>
|
<string name="preferences_audio">声音</string>
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
|
|
||||||
<string name="input_overlay_options">虛擬按鍵設定</string>
|
<string name="input_overlay_options">虛擬按鍵設定</string>
|
||||||
<string name="input_overlay_options_description">調整虛擬按鍵的位置與顯示設定</string>
|
<string name="input_overlay_options_description">調整虛擬按鍵的位置與顯示設定</string>
|
||||||
<string name="edit_overlay_layout">編輯虛擬按鍵</string>
|
<string name="edit_overlay_layout">調整虛擬按鍵</string>
|
||||||
<string name="edit_overlay_layout_description">調整虛擬按鍵的位置和大小</string>
|
<string name="edit_overlay_layout_description">調整虛擬按鍵的位置和大小</string>
|
||||||
|
|
||||||
|
|
||||||
@@ -253,8 +253,8 @@
|
|||||||
<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">授予 Eden 傳送通知的權限以使用模擬器的特定功能</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>
|
||||||
@@ -268,8 +268,8 @@
|
|||||||
<string name="device_manufacturer">製造商</string>
|
<string name="device_manufacturer">製造商</string>
|
||||||
<string name="device_model">型號</string>
|
<string name="device_model">型號</string>
|
||||||
<string name="product">型號代碼</string>
|
<string name="product">型號代碼</string>
|
||||||
<string name="android_version">安卓版本</string>
|
<string name="android_version">Android 版本</string>
|
||||||
<string name="android_security_patch">安卓安全性修補程式等級</string>
|
<string name="android_security_patch">Android 安全性修補程式等級</string>
|
||||||
<string name="build_id">版本號碼</string>
|
<string name="build_id">版本號碼</string>
|
||||||
<string name="general_information">基本資訊</string>
|
<string name="general_information">基本資訊</string>
|
||||||
<string name="hardware">硬體</string>
|
<string name="hardware">硬體</string>
|
||||||
@@ -287,7 +287,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>
|
||||||
@@ -417,17 +417,17 @@
|
|||||||
<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>
|
||||||
<plurals name="saves_import_success">
|
<plurals name="saves_import_success">
|
||||||
<item quantity="other">成功導入 %d 個存檔</item>
|
<item quantity="other">成功匯入 %d 個存檔</item>
|
||||||
</plurals>
|
</plurals>
|
||||||
<string name="no_save_data_found">找不到儲存資料</string>
|
<string name="no_save_data_found">找不到儲存資料</string>
|
||||||
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
|
<string name="verify_installed_content">驗證已安裝內容的完整性</string>
|
||||||
@@ -451,7 +451,7 @@
|
|||||||
|
|
||||||
<!-- 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">從 Switch 系統主畫面啟動應用程式(目前模擬區域尚不支援臺灣、澳洲、中國、南韓啟動 Qlaunch)</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_firmware">未安裝韌體</string>
|
||||||
@@ -578,7 +578,7 @@
|
|||||||
<string name="skip_cpu_inner_invalidation">跳過 CPU 內部失效處理</string>
|
<string name="skip_cpu_inner_invalidation">跳過 CPU 內部失效處理</string>
|
||||||
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些 CPU 端快取的失效處理,減少 CPU 使用率並提高其性能。可能會導致某些遊戲出現故障或當機</string>
|
<string name="skip_cpu_inner_invalidation_description">在記憶體更新期間跳過某些 CPU 端快取的失效處理,減少 CPU 使用率並提高其性能。可能會導致某些遊戲出現故障或當機</string>
|
||||||
<string name="fix_bloom_effects">修正光暈特效</string>
|
<string name="fix_bloom_effects">修正光暈特效</string>
|
||||||
<string name="fix_bloom_effects_description">在 \"薩爾達傳說:織夢島\" 和 \"薩爾達傳說:智慧的再現\" 中減少光暈模糊的問題並移除 \"橫衝直撞:狂飆樂園重製版\" 中的光暈效果(適用於 Adreno A6XX - A7XX/ Turnip)。警告:可能會在其它遊戲中導致圖形異常</string>
|
<string name="fix_bloom_effects_description">移除《橫衝直撞:狂飆樂園重製版》中的光暈效果</string>
|
||||||
<string name="emulate_bgr565">模擬 BGR565</string>
|
<string name="emulate_bgr565">模擬 BGR565</string>
|
||||||
<string name="emulate_bgr565_description">修正遊戲中出現的色彩反轉、圖形異常或陰影異常</string>
|
<string name="emulate_bgr565_description">修正遊戲中出現的色彩反轉、圖形異常或陰影異常</string>
|
||||||
<string name="rescale_hack">啟用舊版重新縮放處理</string>
|
<string name="rescale_hack">啟用舊版重新縮放處理</string>
|
||||||
@@ -601,7 +601,7 @@
|
|||||||
<string name="extensions">擴充功能</string>
|
<string name="extensions">擴充功能</string>
|
||||||
|
|
||||||
<string name="dyna_state">擴展動態狀態</string>
|
<string name="dyna_state">擴展動態狀態</string>
|
||||||
<string name="dyna_state_description">控制擴展動態狀態中可使用的功能數量,較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數</string>
|
<string name="dyna_state_description">控制 Vulkan 擴展動態狀態中可使用的功能數量,較高的數值可根據驅動程式支援的動態狀態減少管線編譯的次數</string>
|
||||||
<string name="disabled">停用</string>
|
<string name="disabled">停用</string>
|
||||||
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
<string name="vertex_input_dynamic_state">頂點輸入動態狀態</string>
|
||||||
<string name="vertex_input_dynamic_state_description">啟用此功能可提供更彈性的頂點輸入處理方式,並可能減少頂點/緩衝區的管線編譯時間</string>
|
<string name="vertex_input_dynamic_state_description">啟用此功能可提供更彈性的頂點輸入處理方式,並可能減少頂點/緩衝區的管線編譯時間</string>
|
||||||
@@ -806,7 +806,7 @@
|
|||||||
<string name="recommended_driver">推薦驅動程式:</string>
|
<string name="recommended_driver">推薦驅動程式:</string>
|
||||||
<string name="gpu_model">GPU 型號</string>
|
<string name="gpu_model">GPU 型號</string>
|
||||||
<string name="unsupported_gpu">不支援的 GPU</string>
|
<string name="unsupported_gpu">不支援的 GPU</string>
|
||||||
<string name="unsupported_gpu_warning">您的 GPU 不支援驅動程式注入,不建議嘗試設定自訂驅動程式</string>
|
<string name="unsupported_gpu_warning">您的 GPU 不支援驅動程式注入,不建議嘗試安裝自訂驅動程式</string>
|
||||||
|
|
||||||
<!-- Preferences Screen -->
|
<!-- Preferences Screen -->
|
||||||
<string name="preferences_settings">設定</string>
|
<string name="preferences_settings">設定</string>
|
||||||
@@ -815,6 +815,12 @@
|
|||||||
<string name="preferences_graphics">圖形</string>
|
<string name="preferences_graphics">圖形</string>
|
||||||
<string name="preferences_graphics_description">準確度層級、解析度及著色器快取</string>
|
<string name="preferences_graphics_description">準確度層級、解析度及著色器快取</string>
|
||||||
<string name="quick_settings">快捷設定</string>
|
<string name="quick_settings">快捷設定</string>
|
||||||
|
<string name="cheats">金手指</string>
|
||||||
|
<string name="enable_all_cheats">啟用所有金手指</string>
|
||||||
|
<string name="disable_all_cheats">停用所有金手指</string>
|
||||||
|
<string name="unnamed_cheat">未命名的金手指</string>
|
||||||
|
<string name="enable_cheats_by_default">預設啟用金手指</string>
|
||||||
|
<string name="enable_cheats_by_default_description">在遊戲啟動時啟用一般金手指</string>
|
||||||
<string name="enable_quick_settings">啟用快捷設定</string>
|
<string name="enable_quick_settings">啟用快捷設定</string>
|
||||||
<string name="enable_quick_settings_description">允許透過滑動和選單按鈕存取快捷設定選單</string>
|
<string name="enable_quick_settings_description">允許透過滑動和選單按鈕存取快捷設定選單</string>
|
||||||
<string name="preferences_audio">音訊</string>
|
<string name="preferences_audio">音訊</string>
|
||||||
@@ -831,9 +837,9 @@
|
|||||||
<string name="custom_save_directory">遊戲儲存資料路徑</string>
|
<string name="custom_save_directory">遊戲儲存資料路徑</string>
|
||||||
<string name="custom_save_directory_description">設定遊戲儲存資料的自訂路徑</string>
|
<string name="custom_save_directory_description">設定遊戲儲存資料的自訂路徑</string>
|
||||||
<string name="reset_to_nand">重設為預設值</string>
|
<string name="reset_to_nand">重設為預設值</string>
|
||||||
<string name="migrate_save_data">遷移儲存資料</string>
|
<string name="migrate_save_data">移動儲存資料</string>
|
||||||
<string name="migrate_save_data_question">您要將現有的儲存資料移至新位置嗎?</string>
|
<string name="migrate_save_data_question">您要將現有的儲存資料移至新位置嗎?</string>
|
||||||
<string name="save_migration_complete">成功遷移儲存資料</string>
|
<string name="save_migration_complete">儲存資料遷移成功</string>
|
||||||
<string name="save_migration_failed">儲存資料遷移失敗</string>
|
<string name="save_migration_failed">儲存資料遷移失敗</string>
|
||||||
<string name="save_directory_set">存檔目錄設定完成</string>
|
<string name="save_directory_set">存檔目錄設定完成</string>
|
||||||
<string name="destination_has_saves">所選取的位置已有儲存資料,是否要取代該檔案?</string>
|
<string name="destination_has_saves">所選取的位置已有儲存資料,是否要取代該檔案?</string>
|
||||||
@@ -889,10 +895,10 @@
|
|||||||
<string name="save_data_deleted_successfully">儲存資料已成功刪除</string>
|
<string name="save_data_deleted_successfully">儲存資料已成功刪除</string>
|
||||||
<string name="select_content_type">內容類型</string>
|
<string name="select_content_type">內容類型</string>
|
||||||
<string name="updates_and_dlc">更新及 DLC</string>
|
<string name="updates_and_dlc">更新及 DLC</string>
|
||||||
<string name="mods_and_cheats">模組及金手指</string>
|
<string name="mods_and_cheats">Mod 和金手指</string>
|
||||||
<string name="addon_notice">重要的˙附加元件通知</string>
|
<string name="addon_notice">注意!</string>
|
||||||
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
|
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
|
||||||
<string name="addon_notice_description">若要安裝模組及金手指,您必須選擇一個包含 cheats/、romfs/ 或 exefs/ 的目錄。我們無法驗證這些內容是否與您的遊戲相容,所以請謹慎安裝!</string>
|
<string name="addon_notice_description">若要安裝 Mod 和金手指,您必須選擇一個包含 cheats/、romfs/ 或 exefs/ 的目錄。我們無法驗證這些內容是否與您的遊戲相容,所以請謹慎安裝!</string>
|
||||||
<string name="invalid_directory">無效的目錄</string>
|
<string name="invalid_directory">無效的目錄</string>
|
||||||
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
|
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
|
||||||
<string name="invalid_directory_description">請確保您選取的目錄包含 cheats/、romfs/ 或 exefs/ 資料夾,然後再試一次</string>
|
<string name="invalid_directory_description">請確保您選取的目錄包含 cheats/、romfs/ 或 exefs/ 資料夾,然後再試一次</string>
|
||||||
@@ -979,7 +985,7 @@
|
|||||||
<string name="emulation_pause">暫停模擬</string>
|
<string name="emulation_pause">暫停模擬</string>
|
||||||
<string name="emulation_unpause">繼續模擬</string>
|
<string name="emulation_unpause">繼續模擬</string>
|
||||||
<string name="emulation_input_overlay">疊加層/虛擬按鍵設定</string>
|
<string name="emulation_input_overlay">疊加層/虛擬按鍵設定</string>
|
||||||
<string name="load_amiibo">導入 Amiibo</string>
|
<string name="load_amiibo">匯入 Amiibo</string>
|
||||||
<string name="touchscreen">觸控螢幕</string>
|
<string name="touchscreen">觸控螢幕</string>
|
||||||
<string name="lock_drawer">鎖定側邊選單</string>
|
<string name="lock_drawer">鎖定側邊選單</string>
|
||||||
<string name="unlock_drawer">解鎖側邊選單</string>
|
<string name="unlock_drawer">解鎖側邊選單</string>
|
||||||
@@ -1126,6 +1132,16 @@
|
|||||||
<string name="freedreno_clear_all">全部清除</string>
|
<string name="freedreno_clear_all">全部清除</string>
|
||||||
<string name="freedreno_saved">Freedreno 設定已儲存</string>
|
<string name="freedreno_saved">Freedreno 設定已儲存</string>
|
||||||
<string name="freedreno_cleared_all">已清除所有 Freedreno 變數</string>
|
<string name="freedreno_cleared_all">已清除所有 Freedreno 變數</string>
|
||||||
|
<string name="freedreno_variable_added">變數 %1$s 已新增</string>
|
||||||
|
<string name="freedreno_preset_applied">設定檔 \"%1$s\" 已套用</string>
|
||||||
|
<string name="freedreno_error_empty_name">變數名稱不可空白</string>
|
||||||
|
<string name="freedreno_error_setting_variable">變數設定失敗</string>
|
||||||
|
<string name="freedreno_info_title">關於 Freedreno 設定</string>
|
||||||
|
<string name="freedreno_info_description">透過調整 Freedreno/Turnip GPU 驅動程式的設定來偵錯、分析和最佳化效能,會自動儲存變更。詳情請參閱 https://docs.mesa3d.org/drivers/freedreno.html</string>
|
||||||
|
<string name="freedreno_per_game_title">Freedreno 設定</string>
|
||||||
|
<string name="freedreno_per_game_description">調整此遊戲的 GPU 驅動程式設定</string>
|
||||||
|
<string name="freedreno_per_game_saved">Freedreno 設定已儲存</string>
|
||||||
|
|
||||||
<!-- Gamepad Buttons -->
|
<!-- Gamepad Buttons -->
|
||||||
<string name="gamepad_d_pad">方向鍵</string>
|
<string name="gamepad_d_pad">方向鍵</string>
|
||||||
<string name="gamepad_left_stick">左搖桿</string>
|
<string name="gamepad_left_stick">左搖桿</string>
|
||||||
@@ -1134,14 +1150,17 @@
|
|||||||
<string name="gamepad_screenshot">螢幕截圖</string>
|
<string name="gamepad_screenshot">螢幕截圖</string>
|
||||||
|
|
||||||
<!-- Disk shader cache -->
|
<!-- Disk shader cache -->
|
||||||
<string name="building_shaders">正在建置著色器</string>
|
<string name="building_shaders">正在編譯著色器</string>
|
||||||
|
|
||||||
<!-- App options -->
|
<!-- App options -->
|
||||||
<string name="change_app_theme">變更應用程式主題</string>
|
<string name="change_app_theme">變更應用程式主題</string>
|
||||||
<string name="theme_default">預設</string>
|
<string name="theme_default">預設</string>
|
||||||
<string name="theme_material_you">質感設計3</string>
|
<string name="theme_material_you">Material You</string>
|
||||||
<string name="app_settings">Eden 介面設定</string>
|
<string name="app_settings">Eden 介面設定</string>
|
||||||
<string name="theme_and_color">主題和顏色</string>
|
<string name="theme_and_color">主題和顏色</string>
|
||||||
|
<string name="fullscreen_mode">全螢幕模式</string>
|
||||||
|
<string name="fullscreen_mode_description">在使用 Eden 時隱藏 Android 系統的導覽列,在直向時從螢幕底部往上滑以暫時顯示它們;橫向時則從螢幕側邊往內滑動</string>
|
||||||
|
|
||||||
<!-- Theme Modes -->
|
<!-- Theme Modes -->
|
||||||
<string name="change_theme_mode">變更主題模式</string>
|
<string name="change_theme_mode">變更主題模式</string>
|
||||||
<string name="theme_mode_follow_system">跟隨系統</string>
|
<string name="theme_mode_follow_system">跟隨系統</string>
|
||||||
@@ -1150,7 +1169,13 @@
|
|||||||
|
|
||||||
<!-- Black backgrounds theme -->
|
<!-- Black backgrounds theme -->
|
||||||
<string name="use_black_backgrounds">黑色背景</string>
|
<string name="use_black_backgrounds">黑色背景</string>
|
||||||
<string name="use_black_backgrounds_description">使用深色主題時,套用黑色背景。</string>
|
<string name="use_black_backgrounds_description">使用深色主題時套用黑色背景</string>
|
||||||
|
|
||||||
|
<!-- Buttons -->
|
||||||
|
<string name="enable_folder_button">遊戲資料夾</string>
|
||||||
|
<string name="enable_folder_button_description">在 Eden 首頁顯示新增遊戲資料夾的按鈕</string>
|
||||||
|
<string name="enable_qlaunch_button">QLaunch</string>
|
||||||
|
<string name="enable_qlaunch_button_description">在 Eden 首頁顯示 QLaunch 按鈕</string>
|
||||||
|
|
||||||
<!-- App Language -->
|
<!-- App Language -->
|
||||||
<string name="app_language">語言</string>
|
<string name="app_language">語言</string>
|
||||||
@@ -1158,10 +1183,12 @@
|
|||||||
<string name="app_language_system">跟隨系統</string>
|
<string name="app_language_system">跟隨系統</string>
|
||||||
<!-- Static Themes -->
|
<!-- Static Themes -->
|
||||||
<string name="static_theme_color">主題色彩</string>
|
<string name="static_theme_color">主題色彩</string>
|
||||||
|
<string name="eden_theme">Eden</string>
|
||||||
<string name="violet">紫色</string>
|
<string name="violet">紫色</string>
|
||||||
<string name="blue">藍色</string>
|
<string name="blue">藍色</string>
|
||||||
<string name="cyan">青色</string>
|
<string name="cyan">青色</string>
|
||||||
<string name="red">紅色</string>
|
<string name="red">紅色</string>
|
||||||
|
<string name="green">綠色</string>
|
||||||
<string name="yellow">黃色</string>
|
<string name="yellow">黃色</string>
|
||||||
<string name="orange">橘色</string>
|
<string name="orange">橘色</string>
|
||||||
<string name="pink">粉紅色</string>
|
<string name="pink">粉紅色</string>
|
||||||
@@ -1190,6 +1217,20 @@
|
|||||||
<string name="airplane_mode">飛航模式</string>
|
<string name="airplane_mode">飛航模式</string>
|
||||||
<string name="airplane_mode_description">將飛航模式傳遞給 Switch 作業系統</string>
|
<string name="airplane_mode_description">將飛航模式傳遞給 Switch 作業系統</string>
|
||||||
|
|
||||||
|
<string name="enable_overlay">啟用小程式虛擬按鍵</string>
|
||||||
|
<string name="enable_overlay_description">啟用 Horizon OS 內建的小程式虛擬按鍵,長按 Home 鍵 1 秒以顯示虛擬按鍵</string>
|
||||||
|
|
||||||
|
<!-- Profile Management -->
|
||||||
|
<string name="profile_manager">使用者管理</string>
|
||||||
|
<string name="profile_manager_description">更改使用者名稱、圖片及新增或刪除使用者</string>
|
||||||
|
<string name="profile_add_user">新增使用者</string>
|
||||||
|
<string name="profile_new_user">新增使用者</string>
|
||||||
|
<string name="profile_edit_user">編輯使用者資料</string>
|
||||||
|
<string name="profile_edit">編輯</string>
|
||||||
|
<string name="profile_delete">刪除</string>
|
||||||
|
<string name="profile_username">使用者名稱</string>
|
||||||
|
<string name="profile_uuid">使用者 ID (通用唯一辨識碼)</string>
|
||||||
|
<string name="profile_uuid_description">這是此使用者設定檔的唯一識別碼,建立後就無法進行更改</string>
|
||||||
<!-- Licenses screen strings -->
|
<!-- Licenses screen strings -->
|
||||||
<string name="licenses">授權</string>
|
<string name="licenses">授權</string>
|
||||||
<string name="license_fidelityfx_fsr_description">來自 AMD 的升級圖像品質</string>
|
<string name="license_fidelityfx_fsr_description">來自 AMD 的升級圖像品質</string>
|
||||||
|
|||||||
@@ -498,7 +498,7 @@
|
|||||||
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
|
<string name="user_data_import_failed_description">Make sure the user data folders are at the root of the zip folder and contain a config file at config/config.ini and try again.</string>
|
||||||
<string name="discord_link" translatable="false">https://discord.gg/HstXbPch7X</string>
|
<string name="discord_link" translatable="false">https://discord.gg/HstXbPch7X</string>
|
||||||
<string name="stoat_link" translatable="false">https://stt.gg/qKgFEAbH</string>
|
<string name="stoat_link" translatable="false">https://stt.gg/qKgFEAbH</string>
|
||||||
<string name="x_link" translatable="false">https://nitter.poast.org/edenemuofficial</string>
|
<string name="x_link" translatable="false">https://x.com/edenemuofficial</string>
|
||||||
<string name="website_link" translatable="false">https://eden-emu.dev</string>
|
<string name="website_link" translatable="false">https://eden-emu.dev</string>
|
||||||
<string name="github_link" translatable="false">https://git.eden-emu.dev/eden-emu</string>
|
<string name="github_link" translatable="false">https://git.eden-emu.dev/eden-emu</string>
|
||||||
|
|
||||||
|
|||||||
+202
-80
@@ -7,18 +7,25 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "common/bit_util.h"
|
||||||
#include "common/fs/file.h"
|
#include "common/fs/file.h"
|
||||||
#include "common/fs/fs.h"
|
#include "common/fs/fs.h"
|
||||||
|
#include "common/fs/fs_types.h"
|
||||||
#ifdef __ANDROID__
|
#ifdef __ANDROID__
|
||||||
#include "common/fs/fs_android.h"
|
#include "common/fs/fs_android.h"
|
||||||
#endif
|
#endif
|
||||||
#include "common/logging.h"
|
#include "common/logging.h"
|
||||||
|
#include "common/literals.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#include <share.h>
|
#include <share.h>
|
||||||
|
#include <windows.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
@@ -244,42 +251,162 @@ FileType IOFile::GetType() const {
|
|||||||
return file_type;
|
return file_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(__unix__)
|
||||||
|
static int PlatformMapReadOnly(IOFile& io, const char* path) {
|
||||||
|
io.mmap_fd = open(path, O_RDONLY);
|
||||||
|
if (io.mmap_fd > 0) {
|
||||||
|
struct stat st;
|
||||||
|
fstat(io.mmap_fd, &st);
|
||||||
|
io.mmap_size = st.st_size;
|
||||||
|
|
||||||
|
int map_flags = MAP_PRIVATE;
|
||||||
|
#ifdef MAP_PREFAULT_READ
|
||||||
|
// Prefaults reads so the final resulting pagetable from this big stupid mmap()
|
||||||
|
// isn't comically lazily loaded, we just coalesce everything in-place for our
|
||||||
|
// lovely mmap flags; if we didn't prefault the reads the page table will be
|
||||||
|
// constructed in-place (i.e on a read-by-read basis) causing lovely soft-faults
|
||||||
|
// which would nuke any performance gains.
|
||||||
|
//
|
||||||
|
// This of course incurs a cost in the initial mmap(2) call, but that is fine.
|
||||||
|
map_flags |= MAP_PREFAULT_READ;
|
||||||
|
#endif
|
||||||
|
#ifdef MAP_NOSYNC
|
||||||
|
// This causes physical media to not be synched to our file/memory
|
||||||
|
// This means that if the read-only file is written to, we won't see changes
|
||||||
|
// or we may see changes which are just funnily scattered, in any case
|
||||||
|
// this presumes the files won't be changed during execution
|
||||||
|
//
|
||||||
|
// Do not ever use this on write files (if we ever support that); this will create
|
||||||
|
// a fun amount of fragmentation on the disk.
|
||||||
|
map_flags |= MAP_NOSYNC;
|
||||||
|
#endif
|
||||||
|
#if defined(NDEBUG) && defined(MAP_NOCORE)
|
||||||
|
map_flags |= MAP_NOCORE;
|
||||||
|
#endif
|
||||||
|
#ifdef MAP_HUGE_2MB
|
||||||
|
map_flags |= MAP_HUGE_2MB; //2mb pages
|
||||||
|
#elif defined(MAP_ALIGNED)
|
||||||
|
// File must be big enough that it's worth to super align. We can't just super-align every
|
||||||
|
// file otherwise we will run out of alignments for actually important files :)
|
||||||
|
// System doesn't guarantee a super alignment, but if it's available it will delete
|
||||||
|
// about 3 layers(?) of the TLB tree for each read/write.
|
||||||
|
// Again the cost of faults may make this negligible gains, but hey, we gotta work
|
||||||
|
// what we gotta work with.
|
||||||
|
map_flags |= MAP_ALIGNED(21); //2^21 = 2mb use 2MB pages
|
||||||
|
#endif
|
||||||
|
io.mmap_base = (u8*)mmap(nullptr, io.mmap_size, PROT_READ, map_flags, io.mmap_fd, 0);
|
||||||
|
if (io.mmap_base == MAP_FAILED) {
|
||||||
|
close(io.mmap_fd);
|
||||||
|
io.mmap_fd = -1;
|
||||||
|
} else {
|
||||||
|
using namespace Common::Literals;
|
||||||
|
// For small files it is acceptable to use a full readahead
|
||||||
|
// See https://github.com/torvalds/linux/blob/e80d033851b3bc94c3d254ac66660ddd0a49d72c/include/linux/pagemap.h#L1392
|
||||||
|
if (u64(st.st_size) >= 256_MiB) {
|
||||||
|
posix_madvise(io.mmap_base, io.mmap_size, POSIX_MADV_RANDOM);
|
||||||
|
} else {
|
||||||
|
posix_madvise(io.mmap_base, io.mmap_size, POSIX_MADV_SEQUENTIAL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return io.mmap_fd;
|
||||||
|
}
|
||||||
|
static void PlatformUnmap(IOFile& io) {
|
||||||
|
if (io.mmap_fd != -1) {
|
||||||
|
munmap(io.mmap_base, io.mmap_size);
|
||||||
|
close(io.mmap_fd);
|
||||||
|
io.mmap_fd = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
// NO IMPLEMENTATION YET
|
||||||
|
#else
|
||||||
|
static int PlatformMapReadOnly(IOFile& io, const wchar_t* path) {
|
||||||
|
io.file_handle = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, nullptr);
|
||||||
|
if (HANDLE(io.file_handle) != INVALID_HANDLE_VALUE) {
|
||||||
|
io.mapping_handle = CreateFileMappingW(HANDLE(io.file_handle), nullptr, PAGE_READONLY, 0, 0, nullptr);
|
||||||
|
if (io.mapping_handle) {
|
||||||
|
io.mmap_base = (u8*)MapViewOfFile(HANDLE(io.mapping_handle), FILE_MAP_READ, 0, 0, 0);
|
||||||
|
if (io.mmap_base) {
|
||||||
|
_LARGE_INTEGER pvalue;
|
||||||
|
GetFileSizeEx(io.file_handle, &pvalue);
|
||||||
|
io.mmap_size = uint32_t(pvalue.QuadPart);
|
||||||
|
} else {
|
||||||
|
CloseHandle(io.mapping_handle);
|
||||||
|
CloseHandle(io.file_handle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
CloseHandle(io.file_handle);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
static void PlatformUnmap(IOFile& io) {
|
||||||
|
if(io.mapping_handle) {
|
||||||
|
if(io.mmap_base)
|
||||||
|
UnmapViewOfFile(HANDLE(io.mmap_base));
|
||||||
|
CloseHandle(HANDLE(io.mapping_handle));
|
||||||
|
}
|
||||||
|
if(io.file_handle != INVALID_HANDLE_VALUE)
|
||||||
|
CloseHandle(HANDLE(io.file_handle));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
|
void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, FileShareFlag flag) {
|
||||||
Close();
|
Close();
|
||||||
|
|
||||||
file_path = path;
|
file_path = path;
|
||||||
file_access_mode = mode;
|
file_access_mode = mode;
|
||||||
file_type = type;
|
file_type = type;
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
// TODO: this probably can use better logic but oh well I'm not a windowser
|
||||||
|
file_handle = nullptr;
|
||||||
|
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
|
||||||
|
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "Error mmap'ing file"); //: {}", path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (file_handle == nullptr) {
|
||||||
if (flag != FileShareFlag::ShareNone) {
|
if (flag != FileShareFlag::ShareNone) {
|
||||||
file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag));
|
file = _wfsopen(path.c_str(), AccessModeToWStr(mode, type), ToWindowsFileShareFlag(flag));
|
||||||
} else {
|
} else {
|
||||||
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
|
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#elif __ANDROID__
|
#elif __ANDROID__
|
||||||
if (Android::IsContentUri(path)) {
|
if (Android::IsContentUri(path)) {
|
||||||
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
|
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
|
||||||
const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read);
|
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "Error mmap'ing file: {}", path.c_str());
|
||||||
|
int const fd = Android::OpenContentUri(path, Android::OpenMode::Read);
|
||||||
if (fd != -1) {
|
if (fd != -1) {
|
||||||
file = fdopen(fd, "r");
|
file = fdopen(fd, "r");
|
||||||
const auto error_num = errno;
|
if (errno != 0 && file == nullptr)
|
||||||
if (error_num != 0 && file == nullptr) {
|
LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(), strerror(errno));
|
||||||
LOG_ERROR(Common_Filesystem, "Error opening file: {}, error: {}", path.c_str(),
|
|
||||||
strerror(error_num));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str());
|
LOG_ERROR(Common_Filesystem, "Error opening file: {}", path.c_str());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||||
}
|
}
|
||||||
|
#elif defined(__HAIKU__) || defined(__managarm__) || defined(__OPENORBIS__) || defined(__APPLE__)
|
||||||
|
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||||
|
#elif defined(__unix__)
|
||||||
|
if (type == FileType::BinaryFile && mode == FileAccessMode::Read) {
|
||||||
|
if (PlatformMapReadOnly(*this, path.c_str()) == -1) {
|
||||||
|
LOG_ERROR(Common_Filesystem, "Error mmap'ing file: {}", path.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mmap_fd == -1) {
|
||||||
|
file = std::fopen(path.c_str(), AccessModeToStr(mode, type)); // mmap(2) failed or simply we can't use it
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
|
// Some other fancy OS (ahem fucking Darwin/Mac OSX)
|
||||||
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
file = std::fopen(path.c_str(), AccessModeToStr(mode, type));
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!IsOpen()) {
|
if (!IsOpen()) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to open the file at path={}, ec_message={}",
|
||||||
@@ -288,25 +415,25 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IOFile::Close() {
|
void IOFile::Close() {
|
||||||
if (!IsOpen()) {
|
#if defined(__APPLE__)
|
||||||
return;
|
// NO IMPLEMENTATION YET
|
||||||
}
|
#else
|
||||||
|
PlatformUnmap(*this);
|
||||||
|
#endif
|
||||||
|
if (file) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
const auto close_result = std::fclose(file) == 0;
|
const auto close_result = std::fclose(file) == 0;
|
||||||
|
|
||||||
if (!close_result) {
|
if (!close_result) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to close the file at path={}, ec_message={}",
|
||||||
PathToUTF8String(file_path), ec.message());
|
PathToUTF8String(file_path), ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
file = nullptr;
|
file = nullptr;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool IOFile::IsOpen() const {
|
bool IOFile::IsOpen() const {
|
||||||
return file != nullptr;
|
return file != nullptr || IsMappedFile();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string IOFile::ReadString(size_t length) const {
|
std::string IOFile::ReadString(size_t length) const {
|
||||||
@@ -323,80 +450,65 @@ size_t IOFile::WriteString(std::span<const char> string) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool IOFile::Flush() const {
|
bool IOFile::Flush() const {
|
||||||
if (!IsOpen()) {
|
ASSERT(!IsMappedFile());
|
||||||
return false;
|
if (file) {
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
auto const flush_result = std::fflush(file) == 0;
|
||||||
#ifdef _WIN32
|
|
||||||
const auto flush_result = std::fflush(file) == 0;
|
|
||||||
#else
|
|
||||||
const auto flush_result = std::fflush(file) == 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!flush_result) {
|
if (!flush_result) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to flush the file at path={}, ec_message={}",
|
||||||
PathToUTF8String(file_path), ec.message());
|
PathToUTF8String(file_path), ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
return flush_result;
|
return flush_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IOFile::Commit() const {
|
|
||||||
if (!IsOpen()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IOFile::Commit() const {
|
||||||
|
ASSERT(!IsMappedFile());
|
||||||
|
if (file) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
|
const auto commit_result = std::fflush(file) == 0 && _commit(fileno(file)) == 0;
|
||||||
#else
|
#else
|
||||||
const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
|
const auto commit_result = std::fflush(file) == 0 && fsync(fileno(file)) == 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!commit_result) {
|
if (!commit_result) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to commit the file at path={}, ec_message={}",
|
||||||
PathToUTF8String(file_path), ec.message());
|
PathToUTF8String(file_path), ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
return commit_result;
|
return commit_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IOFile::SetSize(u64 size) const {
|
|
||||||
if (!IsOpen()) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IOFile::SetSize(u64 size) const {
|
||||||
|
ASSERT(!IsMappedFile());
|
||||||
|
if (file) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
const auto set_size_result = _chsize_s(fileno(file), static_cast<s64>(size)) == 0;
|
const auto set_size_result = _chsize_s(fileno(file), s64(size)) == 0;
|
||||||
#else
|
#else
|
||||||
const auto set_size_result = ftruncate(fileno(file), static_cast<s64>(size)) == 0;
|
const auto set_size_result = ftruncate(fileno(file), s64(size)) == 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!set_size_result) {
|
if (!set_size_result) {
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to resize the file at path={}, size={}, ec_message={}",
|
||||||
PathToUTF8String(file_path), size, ec.message());
|
PathToUTF8String(file_path), size, ec.message());
|
||||||
}
|
}
|
||||||
|
|
||||||
return set_size_result;
|
return set_size_result;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
u64 IOFile::GetSize() const {
|
u64 IOFile::GetSize() const {
|
||||||
if (!IsOpen()) {
|
if (IsMappedFile())
|
||||||
return 0;
|
return mmap_size;
|
||||||
}
|
if (file) {
|
||||||
|
// Flush any unwritten buffered data into the file prior to retrieving the file mmap_size.
|
||||||
// Flush any unwritten buffered data into the file prior to retrieving the file size.
|
|
||||||
std::fflush(file);
|
std::fflush(file);
|
||||||
|
#if __ANDROID__
|
||||||
#ifdef __ANDROID__
|
|
||||||
u64 file_size = 0;
|
u64 file_size = 0;
|
||||||
if (Android::IsContentUri(file_path)) {
|
if (Android::IsContentUri(file_path)) {
|
||||||
file_size = Android::GetSize(file_path);
|
file_size = Android::GetSize(file_path);
|
||||||
@@ -406,54 +518,64 @@ u64 IOFile::GetSize() const {
|
|||||||
file_size = fs::file_size(file_path, ec);
|
file_size = fs::file_size(file_path, ec);
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERROR(Common_Filesystem,
|
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file mmap_size of path={}, ec_message={}",
|
||||||
"Failed to retrieve the file size of path={}, ec_message={}",
|
|
||||||
PathToUTF8String(file_path), ec.message());
|
PathToUTF8String(file_path), ec.message());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
std::error_code ec;
|
std::error_code ec;
|
||||||
|
auto const file_size = fs::file_size(file_path, ec);
|
||||||
const auto file_size = fs::file_size(file_path, ec);
|
|
||||||
|
|
||||||
if (ec) {
|
if (ec) {
|
||||||
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file size of path={}, ec_message={}",
|
LOG_ERROR(Common_Filesystem, "Failed to retrieve the file mmap_size of path={}, ec_message={}",
|
||||||
PathToUTF8String(file_path), ec.message());
|
PathToUTF8String(file_path), ec.message());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return file_size;
|
return file_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
|
||||||
if (!IsOpen()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
errno = 0;
|
|
||||||
|
|
||||||
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
|
||||||
|
|
||||||
if (!seek_result) {
|
|
||||||
const auto ec = std::error_code{errno, std::generic_category()};
|
|
||||||
LOG_ERROR(Common_Filesystem,
|
|
||||||
"Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
|
|
||||||
PathToUTF8String(file_path), offset, origin, ec.message());
|
|
||||||
}
|
|
||||||
|
|
||||||
return seek_result;
|
|
||||||
}
|
|
||||||
|
|
||||||
s64 IOFile::Tell() const {
|
|
||||||
if (!IsOpen()) {
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IOFile::Seek(s64 offset, SeekOrigin origin) const {
|
||||||
|
if (IsMappedFile()) {
|
||||||
|
// fuck you to whoever made this method const
|
||||||
|
switch (origin) {
|
||||||
|
case SeekOrigin::SetOrigin:
|
||||||
|
mmap_offset = s64(offset);
|
||||||
|
break;
|
||||||
|
case SeekOrigin::CurrentPosition:
|
||||||
|
mmap_offset += s64(offset);
|
||||||
|
break;
|
||||||
|
case SeekOrigin::End:
|
||||||
|
mmap_offset = s64(mmap_size) + s64(offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (file) {
|
||||||
errno = 0;
|
errno = 0;
|
||||||
|
const auto seek_result = fseeko(file, offset, ToSeekOrigin(origin)) == 0;
|
||||||
|
if (!seek_result) {
|
||||||
|
const auto ec = std::error_code{errno, std::generic_category()};
|
||||||
|
LOG_ERROR(Common_Filesystem, "Failed to seek the file at path={}, offset={}, origin={}, ec_message={}",
|
||||||
|
PathToUTF8String(file_path), offset, origin, ec.message());
|
||||||
|
}
|
||||||
|
return seek_result;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
s64 IOFile::Tell() const {
|
||||||
|
if (IsMappedFile()) {
|
||||||
|
errno = 0;
|
||||||
|
return s64(mmap_offset);
|
||||||
|
}
|
||||||
|
if (file) {
|
||||||
|
errno = 0;
|
||||||
return ftello(file);
|
return ftello(file);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Common::FS
|
} // namespace Common::FS
|
||||||
|
|||||||
+45
-37
@@ -7,6 +7,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <cstring>
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
@@ -186,19 +187,6 @@ public:
|
|||||||
FileType type = FileType::BinaryFile,
|
FileType type = FileType::BinaryFile,
|
||||||
FileShareFlag flag = FileShareFlag::ShareReadOnly);
|
FileShareFlag flag = FileShareFlag::ShareReadOnly);
|
||||||
|
|
||||||
// #ifdef _WIN32
|
|
||||||
// template <typename Path>
|
|
||||||
// void Open(const Path& path, FileAccessMode mode, FileType type = FileType::BinaryFile,
|
|
||||||
// FileShareFlag flag = FileShareFlag::ShareReadOnly) {
|
|
||||||
// using ValueType = typename Path::value_type;
|
|
||||||
// if constexpr (IsChar<ValueType>) {
|
|
||||||
// Open(ToU8String(path), mode, type, flag);
|
|
||||||
// } else {
|
|
||||||
// Open(std::filesystem::path{path}, mode, type, flag);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
/// Closes the file if it is opened.
|
/// Closes the file if it is opened.
|
||||||
void Close();
|
void Close();
|
||||||
|
|
||||||
@@ -228,8 +216,7 @@ public:
|
|||||||
[[nodiscard]] size_t Read(T& data) const {
|
[[nodiscard]] size_t Read(T& data) const {
|
||||||
if constexpr (IsContiguousContainer<T>) {
|
if constexpr (IsContiguousContainer<T>) {
|
||||||
using ContiguousType = typename T::value_type;
|
using ContiguousType = typename T::value_type;
|
||||||
static_assert(std::is_trivially_copyable_v<ContiguousType>,
|
static_assert(std::is_trivially_copyable_v<ContiguousType>, "Data type must be trivially copyable.");
|
||||||
"Data type must be trivially copyable.");
|
|
||||||
return ReadSpan<ContiguousType>(data);
|
return ReadSpan<ContiguousType>(data);
|
||||||
} else {
|
} else {
|
||||||
return ReadObject(data) ? 1 : 0;
|
return ReadObject(data) ? 1 : 0;
|
||||||
@@ -254,8 +241,7 @@ public:
|
|||||||
[[nodiscard]] size_t Write(const T& data) const {
|
[[nodiscard]] size_t Write(const T& data) const {
|
||||||
if constexpr (IsContiguousContainer<T>) {
|
if constexpr (IsContiguousContainer<T>) {
|
||||||
using ContiguousType = typename T::value_type;
|
using ContiguousType = typename T::value_type;
|
||||||
static_assert(std::is_trivially_copyable_v<ContiguousType>,
|
static_assert(std::is_trivially_copyable_v<ContiguousType>, "Data type must be trivially copyable.");
|
||||||
"Data type must be trivially copyable.");
|
|
||||||
return WriteSpan<ContiguousType>(data);
|
return WriteSpan<ContiguousType>(data);
|
||||||
} else {
|
} else {
|
||||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||||
@@ -282,10 +268,11 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
requires std::is_trivially_copyable_v<T>
|
requires std::is_trivially_copyable_v<T>
|
||||||
[[nodiscard]] size_t ReadSpan(std::span<T> data) const {
|
[[nodiscard]] size_t ReadSpan(std::span<T> data) const {
|
||||||
if (!IsOpen()) {
|
if (IsMappedFile()) {
|
||||||
return 0;
|
std::memcpy(data.data(), mmap_base + mmap_offset, sizeof(T) * data.size());
|
||||||
|
return data.size();
|
||||||
}
|
}
|
||||||
return std::fread(data.data(), sizeof(T), data.size(), file);
|
return IsOpen() ? std::fread(data.data(), sizeof(T), data.size(), file) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -306,12 +293,11 @@ public:
|
|||||||
template <typename T>
|
template <typename T>
|
||||||
[[nodiscard]] size_t WriteSpan(std::span<const T> data) const {
|
[[nodiscard]] size_t WriteSpan(std::span<const T> data) const {
|
||||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||||
|
if (IsMappedFile()) {
|
||||||
if (!IsOpen()) {
|
std::memcpy(mmap_base + mmap_offset, data.data(), sizeof(T) * data.size());
|
||||||
return 0;
|
return data.size();
|
||||||
}
|
}
|
||||||
|
return IsOpen() ? std::fwrite(data.data(), sizeof(T), data.size(), file) : 0;
|
||||||
return std::fwrite(data.data(), sizeof(T), data.size(), file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -334,12 +320,15 @@ public:
|
|||||||
[[nodiscard]] bool ReadObject(T& object) const {
|
[[nodiscard]] bool ReadObject(T& object) const {
|
||||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||||
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
|
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
|
||||||
|
if (IsMappedFile()) {
|
||||||
if (!IsOpen()) {
|
std::memcpy(&object, mmap_base + mmap_offset, sizeof(T));
|
||||||
return false;
|
#ifdef _WIN32
|
||||||
|
return bool(sizeof(T));
|
||||||
|
#else
|
||||||
|
return sizeof(T);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
return IsOpen() ? std::fread(&object, sizeof(T), 1, file) == 1 : false;
|
||||||
return std::fread(&object, sizeof(T), 1, file) == 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -361,12 +350,15 @@ public:
|
|||||||
[[nodiscard]] bool WriteObject(const T& object) const {
|
[[nodiscard]] bool WriteObject(const T& object) const {
|
||||||
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
|
||||||
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
|
static_assert(!std::is_pointer_v<T>, "T must not be a pointer to an object.");
|
||||||
|
if (IsMappedFile()) {
|
||||||
if (!IsOpen()) {
|
std::memcpy(mmap_base + mmap_offset, &object, sizeof(T));
|
||||||
return false;
|
#ifdef _WIN32
|
||||||
|
return sizeof(T) != 0;
|
||||||
|
#else
|
||||||
|
return sizeof(T);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
return IsOpen() ? std::fwrite(&object, sizeof(T), 1, file) == 1 : false;
|
||||||
return std::fwrite(&object, sizeof(T), 1, file) == 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -449,12 +441,28 @@ public:
|
|||||||
*/
|
*/
|
||||||
[[nodiscard]] s64 Tell() const;
|
[[nodiscard]] s64 Tell() const;
|
||||||
|
|
||||||
private:
|
#ifdef _WIN32
|
||||||
|
inline bool IsMappedFile() const noexcept { return mapping_handle != nullptr; }
|
||||||
|
#else // POSIX
|
||||||
|
inline bool IsMappedFile() const noexcept { return mmap_fd != -1; }
|
||||||
|
#endif
|
||||||
|
|
||||||
std::filesystem::path file_path;
|
std::filesystem::path file_path;
|
||||||
FileAccessMode file_access_mode{};
|
FileAccessMode file_access_mode{};
|
||||||
FileType file_type{};
|
FileType file_type{};
|
||||||
|
|
||||||
std::FILE* file = nullptr;
|
std::FILE* file = nullptr;
|
||||||
|
// Any decent system should have mmap() for files
|
||||||
|
// Systems with artifical mmap() limitations should simply change the logic within file.cpp
|
||||||
|
// and reduce the threshold for which the mmap() is set to
|
||||||
|
#ifdef _WIN32
|
||||||
|
void *mapping_handle = nullptr;
|
||||||
|
void *file_handle = nullptr;
|
||||||
|
#else // POSIX
|
||||||
|
int mmap_fd = -1;
|
||||||
|
#endif
|
||||||
|
u8* mmap_base = nullptr;
|
||||||
|
size_t mmap_size = 0;
|
||||||
|
mutable s64 mmap_offset = 0; // fuck you
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Common::FS
|
} // namespace Common::FS
|
||||||
|
|||||||
+108
-6
@@ -116,19 +116,121 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string UTF16ToUTF8(std::u16string_view input) {
|
std::string UTF16ToUTF8(std::u16string_view input) {
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
std::string result;
|
||||||
return convert.to_bytes(input.data(), input.data() + input.size());
|
result.reserve(input.size() * 4);
|
||||||
|
for (size_t i = 0; i < input.size(); ++i) {
|
||||||
|
uint32_t code = input[i];
|
||||||
|
// Handle surrogate pairs
|
||||||
|
if (code >= 0xD800 && code <= 0xDBFF) {
|
||||||
|
if (i + 1 < input.size()) {
|
||||||
|
uint32_t low = input[i + 1];
|
||||||
|
if (low >= 0xDC00 && low <= 0xDFFF) {
|
||||||
|
code = ((code - 0xD800) << 10) + (low - 0xDC00) + 0x10000;
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (code <= 0x7F) {
|
||||||
|
result.push_back(char(code));
|
||||||
|
} else if (code <= 0x7FF) {
|
||||||
|
result.push_back(char(0xC0 | (code >> 6)));
|
||||||
|
result.push_back(char(0x80 | (code & 0x3F)));
|
||||||
|
} else if (code <= 0xFFFF) {
|
||||||
|
result.push_back(char(0xE0 | (code >> 12)));
|
||||||
|
result.push_back(char(0x80 | ((code >> 6) & 0x3F)));
|
||||||
|
result.push_back(char(0x80 | (code & 0x3F)));
|
||||||
|
} else {
|
||||||
|
result.push_back(char(0xF0 | (code >> 18)));
|
||||||
|
result.push_back(char(0x80 | ((code >> 12) & 0x3F)));
|
||||||
|
result.push_back(char(0x80 | ((code >> 6) & 0x3F)));
|
||||||
|
result.push_back(char(0x80 | (code & 0x3F)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string UTF8ToUTF16(std::string_view input) {
|
std::u16string UTF8ToUTF16(std::string_view input) {
|
||||||
std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
|
std::u16string result;
|
||||||
return convert.from_bytes(input.data(), input.data() + input.size());
|
result.reserve(input.size() * 2);
|
||||||
|
for (size_t i = 0; i < input.size(); ) {
|
||||||
|
uint32_t code = 0;
|
||||||
|
unsigned char c = input[i];
|
||||||
|
size_t len = 0;
|
||||||
|
if ((c & 0x80) == 0) {
|
||||||
|
code = c;
|
||||||
|
len = 1;
|
||||||
|
} else if ((c & 0xE0) == 0xC0) {
|
||||||
|
code = c & 0x1F;
|
||||||
|
len = 2;
|
||||||
|
} else if ((c & 0xF0) == 0xE0) {
|
||||||
|
code = c & 0x0F;
|
||||||
|
len = 3;
|
||||||
|
} else if ((c & 0xF8) == 0xF0) {
|
||||||
|
code = c & 0x07;
|
||||||
|
len = 4;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (i + len - 1 >= input.size())
|
||||||
|
break;
|
||||||
|
for (size_t j = 1; j <= len - 1; ++j) {
|
||||||
|
if ((input[i + j] & 0xC0) != 0x80) {
|
||||||
|
code = 0xFFFD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = (code << 6) | (input[i + j] & 0x3F);
|
||||||
|
}
|
||||||
|
if (code <= 0xFFFF) {
|
||||||
|
result.push_back(char16_t(code));
|
||||||
|
} else {
|
||||||
|
code -= 0x10000;
|
||||||
|
result.push_back(char16_t(0xD800 + (code >> 10)));
|
||||||
|
result.push_back(char16_t(0xDC00 + (code & 0x3FF)));
|
||||||
|
}
|
||||||
|
i += len;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u32string UTF8ToUTF32(std::string_view input) {
|
std::u32string UTF8ToUTF32(std::string_view input) {
|
||||||
std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
|
std::u32string result;
|
||||||
return convert.from_bytes(input.data(), input.data() + input.size());
|
result.reserve(input.size());
|
||||||
|
for (size_t i = 0; i < input.size(); ) {
|
||||||
|
uint32_t code = 0;
|
||||||
|
unsigned char c = input[i];
|
||||||
|
size_t len = 0;
|
||||||
|
if ((c & 0x80) == 0) {
|
||||||
|
code = c;
|
||||||
|
len = 1;
|
||||||
|
} else if ((c & 0xE0) == 0xC0) {
|
||||||
|
code = c & 0x1F;
|
||||||
|
len = 2;
|
||||||
|
} else if ((c & 0xF0) == 0xE0) {
|
||||||
|
code = c & 0x0F;
|
||||||
|
len = 3;
|
||||||
|
} else if ((c & 0xF8) == 0xF0) {
|
||||||
|
code = c & 0x07;
|
||||||
|
len = 4;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
if (i + len - 1 >= input.size())
|
||||||
|
break;
|
||||||
|
for (size_t j = 1; j <= len - 1; ++j) {
|
||||||
|
if ((input[i + j] & 0xC0) != 0x80) {
|
||||||
|
code = 0xFFFD;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
code = (code << 6) | (input[i + j] & 0x3F);
|
||||||
|
}
|
||||||
|
result.push_back(code);
|
||||||
|
i += len;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
|
static std::wstring CPToUTF16(u32 code_page, std::string_view input) {
|
||||||
|
|||||||
+12
-11
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -146,16 +143,20 @@ public:
|
|||||||
return m_str;
|
return m_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetLength() const {
|
constexpr size_t GetLength() const {
|
||||||
|
if (std::is_constant_evaluated()) {
|
||||||
|
return Strlen(this->GetString());
|
||||||
|
} else {
|
||||||
return std::strlen(this->GetString());
|
return std::strlen(this->GetString());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
constexpr bool IsEmpty() const {
|
constexpr bool IsEmpty() const {
|
||||||
return *m_str == '\x00';
|
return *m_str == '\x00';
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsMatchHead(const char* p, size_t len) const {
|
constexpr bool IsMatchHead(const char* p, size_t len) const {
|
||||||
return std::strncmp(this->GetString(), p, len) == 0;
|
return Strncmp(this->GetString(), p, len) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Initialize(const Path& rhs) {
|
Result Initialize(const Path& rhs) {
|
||||||
@@ -168,7 +169,7 @@ public:
|
|||||||
R_TRY(this->Preallocate(len + 1));
|
R_TRY(this->Preallocate(len + 1));
|
||||||
|
|
||||||
// Copy the path
|
// Copy the path
|
||||||
const size_t copied = strlcpy(m_write_buffer.Get(), rhs.GetString(), len + 1);
|
const size_t copied = Strlcpy<char>(m_write_buffer.Get(), rhs.GetString(), len + 1);
|
||||||
R_UNLESS(copied == len, ResultUnexpectedInPathA);
|
R_UNLESS(copied == len, ResultUnexpectedInPathA);
|
||||||
|
|
||||||
// Set normalized
|
// Set normalized
|
||||||
@@ -330,14 +331,14 @@ public:
|
|||||||
// Get our write buffer
|
// Get our write buffer
|
||||||
auto* dst = m_write_buffer.Get();
|
auto* dst = m_write_buffer.Get();
|
||||||
if (old_write_buffer.Get() != nullptr && cur_len > 0) {
|
if (old_write_buffer.Get() != nullptr && cur_len > 0) {
|
||||||
strlcpy(dst, old_write_buffer.Get(), cur_len + 1);
|
Strlcpy<char>(dst, old_write_buffer.Get(), cur_len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add separator
|
// Add separator
|
||||||
dst[cur_len] = '/';
|
dst[cur_len] = '/';
|
||||||
|
|
||||||
// Copy the child path
|
// Copy the child path
|
||||||
const size_t copied = strlcpy(dst + cur_len + 1, c, child_len + 1);
|
const size_t copied = Strlcpy<char>(dst + cur_len + 1, c, child_len + 1);
|
||||||
R_UNLESS(copied == child_len, ResultUnexpectedInPathA);
|
R_UNLESS(copied == child_len, ResultUnexpectedInPathA);
|
||||||
|
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
@@ -374,7 +375,7 @@ public:
|
|||||||
if (m_write_buffer.Get() == nullptr) {
|
if (m_write_buffer.Get() == nullptr) {
|
||||||
if (const auto len = std::strlen(m_str); len > 0) {
|
if (const auto len = std::strlen(m_str); len > 0) {
|
||||||
R_TRY(this->Preallocate(len));
|
R_TRY(this->Preallocate(len));
|
||||||
strlcpy(m_write_buffer.Get(), m_str, len + 1);
|
Strlcpy<char>(m_write_buffer.Get(), m_str, len + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -496,7 +497,7 @@ private:
|
|||||||
R_TRY(this->Preallocate(size + 1));
|
R_TRY(this->Preallocate(size + 1));
|
||||||
|
|
||||||
// Copy the path
|
// Copy the path
|
||||||
const size_t copied = strlcpy(m_write_buffer.Get(), path, size + 1);
|
const size_t copied = Strlcpy<char>(m_write_buffer.Get(), path, size + 1);
|
||||||
R_UNLESS(copied >= size, ResultUnexpectedInPathA);
|
R_UNLESS(copied >= size, ResultUnexpectedInPathA);
|
||||||
} else {
|
} else {
|
||||||
// We can just clear the buffer
|
// We can just clear the buffer
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -1217,7 +1217,7 @@ public:
|
|||||||
replaced_src = static_cast<char*>(Allocate(replaced_src_len));
|
replaced_src = static_cast<char*>(Allocate(replaced_src_len));
|
||||||
}
|
}
|
||||||
|
|
||||||
strlcpy(replaced_src, src, replaced_src_len);
|
Strlcpy<char>(replaced_src, src, replaced_src_len);
|
||||||
|
|
||||||
Replace(replaced_src, replaced_src_len, AlternateDirectorySeparator,
|
Replace(replaced_src, replaced_src_len, AlternateDirectorySeparator,
|
||||||
DirectorySeparator);
|
DirectorySeparator);
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
@@ -10,6 +7,85 @@
|
|||||||
|
|
||||||
namespace FileSys {
|
namespace FileSys {
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int Strlen(const T* str) {
|
||||||
|
ASSERT(str != nullptr);
|
||||||
|
|
||||||
|
int length = 0;
|
||||||
|
while (*str++) {
|
||||||
|
++length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int Strnlen(const T* str, std::size_t count) {
|
||||||
|
return Strnlen(str, static_cast<int>(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int Strnlen(const T* str, int count) {
|
||||||
|
ASSERT(str != nullptr);
|
||||||
|
ASSERT(count >= 0);
|
||||||
|
|
||||||
|
int length = 0;
|
||||||
|
while (count-- && *str++) {
|
||||||
|
++length;
|
||||||
|
}
|
||||||
|
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int Strncmp(const T* lhs, const T* rhs, std::size_t count) {
|
||||||
|
return Strncmp(lhs, rhs, static_cast<int>(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr int Strncmp(const T* lhs, const T* rhs, int count) {
|
||||||
|
ASSERT(lhs != nullptr);
|
||||||
|
ASSERT(rhs != nullptr);
|
||||||
|
ASSERT(count >= 0);
|
||||||
|
|
||||||
|
if (count == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
T l, r;
|
||||||
|
do {
|
||||||
|
l = *(lhs++);
|
||||||
|
r = *(rhs++);
|
||||||
|
} while (l && (l == r) && (--count));
|
||||||
|
|
||||||
|
return l - r;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static constexpr int Strlcpy(T* dst, const T* src, std::size_t count) {
|
||||||
|
return Strlcpy<T>(dst, src, static_cast<int>(count));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static constexpr int Strlcpy(T* dst, const T* src, int count) {
|
||||||
|
ASSERT(dst != nullptr);
|
||||||
|
ASSERT(src != nullptr);
|
||||||
|
|
||||||
|
const T* cur = src;
|
||||||
|
if (count > 0) {
|
||||||
|
while ((--count) && *cur) {
|
||||||
|
*(dst++) = *(cur++);
|
||||||
|
}
|
||||||
|
*dst = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*cur) {
|
||||||
|
cur++;
|
||||||
|
}
|
||||||
|
|
||||||
|
return static_cast<int>(cur - src);
|
||||||
|
}
|
||||||
|
|
||||||
enum CharacterEncodingResult {
|
enum CharacterEncodingResult {
|
||||||
CharacterEncodingResult_Success = 0,
|
CharacterEncodingResult_Success = 0,
|
||||||
CharacterEncodingResult_InsufficientLength = 1,
|
CharacterEncodingResult_InsufficientLength = 1,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#include <iphlpapi.h>
|
#include <iphlpapi.h>
|
||||||
#elif defined(__linux__) || defined(__ANDROID__)
|
#elif defined(__linux__) || defined(__ANDROID__) || defined(__APPLE__)
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
#include <ifaddrs.h>
|
#include <ifaddrs.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
@@ -33,6 +33,13 @@
|
|||||||
#include <netinet/if_ether.h>
|
#include <netinet/if_ether.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <netdb.h>
|
#include <netdb.h>
|
||||||
|
// Darwin doesn't define this for some very odd reason
|
||||||
|
// See https://stackoverflow.com/questions/5390164/getting-routing-table-on-macosx-programmatically
|
||||||
|
#ifndef SA_SIZE
|
||||||
|
#define SA_SIZE(sa) \
|
||||||
|
((!(sa) || ((struct sockaddr *)(sa))->sa_len == 0) ? sizeof(long) \
|
||||||
|
: 1 + ( (((struct sockaddr *)(sa))->sa_len - 1) | (sizeof(long) - 1) ) )
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
@@ -104,7 +111,7 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
#else
|
#else
|
||||||
|
|
||||||
std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
||||||
#if defined(__ANDROID__) || defined(__linux__)
|
#if defined(__ANDROID__) || defined(__linux__) || defined(__APPLE__) || defined(__managarm__)
|
||||||
struct ifaddrs* ifaddr = nullptr;
|
struct ifaddrs* ifaddr = nullptr;
|
||||||
if (getifaddrs(&ifaddr) != 0) {
|
if (getifaddrs(&ifaddr) != 0) {
|
||||||
LOG_ERROR(Network, "getifaddrs: {}", std::strerror(errno));
|
LOG_ERROR(Network, "getifaddrs: {}", std::strerror(errno));
|
||||||
@@ -119,8 +126,9 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
u32 flags;
|
u32 flags;
|
||||||
};
|
};
|
||||||
std::vector<RoutingEntry> routes{};
|
std::vector<RoutingEntry> routes{};
|
||||||
#ifdef __ANDROID__
|
#if defined(__ANDROID__) || defined(__APPLE__)
|
||||||
// Even through Linux based, we can't reliably obtain routing information from there :(
|
// Even through Linux based, we can't reliably obtain routing information from there :(
|
||||||
|
// macOS not Linux based and would murder us if we attempt to access /proc
|
||||||
#else
|
#else
|
||||||
if (std::ifstream file("/proc/net/route"); file.is_open()) {
|
if (std::ifstream file("/proc/net/route"); file.is_open()) {
|
||||||
file.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); //ignore header
|
file.ignore((std::numeric_limits<std::streamsize>::max)(), '\n'); //ignore header
|
||||||
@@ -138,7 +146,10 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
std::vector<Network::NetworkInterface> ifaces;
|
std::vector<Network::NetworkInterface> ifaces;
|
||||||
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
|
for (auto ifa = ifaddr; ifa != nullptr; ifa = ifa->ifa_next) {
|
||||||
if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr /* Have a netmask and address */
|
if (ifa->ifa_addr == nullptr || ifa->ifa_netmask == nullptr /* Have a netmask and address */
|
||||||
|
// Apple hates human beings so lets pretend all families are fine
|
||||||
|
#if !defined(__APPLE__) && !defined(__managarm__)
|
||||||
|| ifa->ifa_addr->sa_family != AF_INET /* Must be of kind AF_INET */
|
|| ifa->ifa_addr->sa_family != AF_INET /* Must be of kind AF_INET */
|
||||||
|
#endif
|
||||||
|| (ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) /* Not loopback */
|
|| (ifa->ifa_flags & IFF_UP) == 0 || (ifa->ifa_flags & IFF_LOOPBACK) != 0) /* Not loopback */
|
||||||
continue;
|
continue;
|
||||||
// Just use 0 as the gateway address if not found OR routes are empty :)
|
// Just use 0 as the gateway address if not found OR routes are empty :)
|
||||||
@@ -158,7 +169,7 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
}
|
}
|
||||||
freeifaddrs(ifaddr);
|
freeifaddrs(ifaddr);
|
||||||
return ifaces;
|
return ifaces;
|
||||||
#elif defined(__FreeBSD__)
|
#elif defined(__FreeBSD__) || defined(__APPLE__)
|
||||||
std::vector<Network::NetworkInterface> ifaces;
|
std::vector<Network::NetworkInterface> ifaces;
|
||||||
int fd = ::socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
int fd = ::socket(PF_ROUTE, SOCK_RAW, AF_UNSPEC);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
@@ -198,11 +209,15 @@ std::vector<Network::NetworkInterface> GetAvailableNetworkInterfaces() {
|
|||||||
if (msglen == 0 || msglen < SA_SIZE(sa))
|
if (msglen == 0 || msglen < SA_SIZE(sa))
|
||||||
break;
|
break;
|
||||||
if (i == RTA_NETMASK && sa->sa_family == AF_LINK) {
|
if (i == RTA_NETMASK && sa->sa_family == AF_LINK) {
|
||||||
size_t namelen = 0;
|
|
||||||
struct sockaddr_dl const* sdl = reinterpret_cast<struct sockaddr_dl const*>(sa);
|
struct sockaddr_dl const* sdl = reinterpret_cast<struct sockaddr_dl const*>(sa);
|
||||||
|
#if defined(__FreeBSD__) && __FreeBSD__ < 15
|
||||||
|
iface.name = std::string{::link_ntoa(sdl)};
|
||||||
|
#else
|
||||||
|
size_t namelen = 0;
|
||||||
::link_ntoa_r(sdl, nullptr, &namelen);
|
::link_ntoa_r(sdl, nullptr, &namelen);
|
||||||
iface.name = std::string(namelen, ' ');
|
iface.name = std::string(namelen, ' ');
|
||||||
::link_ntoa_r(sdl, iface.name.data(), &namelen);
|
::link_ntoa_r(sdl, iface.name.data(), &namelen);
|
||||||
|
#endif
|
||||||
std::memcpy(&iface.ip_address, sa, sizeof(struct sockaddr_in));
|
std::memcpy(&iface.ip_address, sa, sizeof(struct sockaddr_in));
|
||||||
}
|
}
|
||||||
msglen -= SA_SIZE(sa);
|
msglen -= SA_SIZE(sa);
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
|
|||||||
|
|
||||||
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
||||||
ir_block.Reset(descriptor);
|
ir_block.Reset(descriptor);
|
||||||
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf);
|
||||||
Optimization::Optimize(ir_block, conf, {});
|
Optimization::Optimize(ir_block, conf, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -366,8 +366,7 @@ A64AddressSpace::A64AddressSpace(const A64::UserConfig& conf)
|
|||||||
|
|
||||||
void A64AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
void A64AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
||||||
ir_block.Reset(descriptor);
|
ir_block.Reset(descriptor);
|
||||||
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); };
|
A64::Translate(ir_block, A64::LocationDescriptor{descriptor}, conf);
|
||||||
A64::Translate(ir_block, A64::LocationDescriptor{descriptor}, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
|
|
||||||
Optimization::Optimize(ir_block, conf, {});
|
Optimization::Optimize(ir_block, conf, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
||||||
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf);
|
||||||
Optimization::Optimize(ir_block, conf, {.sha256 = true});
|
Optimization::Optimize(ir_block, conf, {.sha256 = true});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ A32AddressSpace::A32AddressSpace(const A32::UserConfig& conf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
void A32AddressSpace::GenerateIR(IR::Block& ir_block, IR::LocationDescriptor descriptor) const {
|
||||||
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
A32::Translate(ir_block, A32::LocationDescriptor{descriptor}, conf);
|
||||||
Optimization::Optimize(ir_block, conf, {});
|
Optimization::Optimize(ir_block, conf, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ private:
|
|||||||
// LocationDescriptor ctor() does important ops (like tflags) do not skip
|
// LocationDescriptor ctor() does important ops (like tflags) do not skip
|
||||||
auto const arch_descriptor = A32::LocationDescriptor{descriptor};
|
auto const arch_descriptor = A32::LocationDescriptor{descriptor};
|
||||||
ir_block.Reset(arch_descriptor);
|
ir_block.Reset(arch_descriptor);
|
||||||
A32::Translate(ir_block, arch_descriptor, conf.callbacks, {conf.arch_version, conf.define_unpredictable_behaviour, conf.hook_hint_instructions});
|
A32::Translate(ir_block, arch_descriptor, conf);
|
||||||
Optimization::Optimize(ir_block, conf, polyfill_options);
|
Optimization::Optimize(ir_block, conf, polyfill_options);
|
||||||
return emitter.Emit(ir_block);
|
return emitter.Emit(ir_block);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -254,11 +254,10 @@ private:
|
|||||||
block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE);
|
block_of_code.EnsureMemoryCommitted(MINIMUM_REMAINING_CODESIZE);
|
||||||
|
|
||||||
// JIT Compile
|
// JIT Compile
|
||||||
const auto get_code = [this](u64 vaddr) { return conf.callbacks->MemoryReadCode(vaddr); };
|
|
||||||
// LocationDescriptor ctor() does important ops (like tflags) do not skip
|
// LocationDescriptor ctor() does important ops (like tflags) do not skip
|
||||||
auto const arch_descriptor = A64::LocationDescriptor{descriptor};
|
auto const arch_descriptor = A64::LocationDescriptor{descriptor};
|
||||||
ir_block.Reset(arch_descriptor);
|
ir_block.Reset(arch_descriptor);
|
||||||
A64::Translate(ir_block, arch_descriptor, get_code, {conf.define_unpredictable_behaviour, conf.wall_clock_cntpct});
|
A64::Translate(ir_block, arch_descriptor, conf);
|
||||||
Optimization::Optimize(ir_block, conf, polyfill_options);
|
Optimization::Optimize(ir_block, conf, polyfill_options);
|
||||||
return emitter.Emit(ir_block).entrypoint;
|
return emitter.Emit(ir_block).entrypoint;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,16 @@
|
|||||||
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
#include "dynarmic/frontend/A32/translate/a32_translate.h"
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
#include "dynarmic/frontend/A32/a32_location_descriptor.h"
|
||||||
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
void TranslateArm(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options);
|
void TranslateArm(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf);
|
||||||
void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options);
|
void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf);
|
||||||
|
|
||||||
void Translate(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) {
|
void Translate(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf) {
|
||||||
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(block, descriptor, tcb, options);
|
return (descriptor.TFlag() ? TranslateThumb : TranslateArm)(block, descriptor, conf);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction);
|
bool TranslateSingleArmInstruction(IR::Block& block, LocationDescriptor descriptor, u32 instruction);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
|
||||||
#include "dynarmic/interface/A32/arch_version.h"
|
#include "dynarmic/interface/A32/arch_version.h"
|
||||||
|
#include "dynarmic/interface/A32/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::IR {
|
namespace Dynarmic::IR {
|
||||||
class Block;
|
class Block;
|
||||||
@@ -20,28 +21,14 @@ namespace Dynarmic::A32 {
|
|||||||
class LocationDescriptor;
|
class LocationDescriptor;
|
||||||
struct TranslateCallbacks;
|
struct TranslateCallbacks;
|
||||||
|
|
||||||
struct TranslationOptions {
|
|
||||||
ArchVersion arch_version;
|
|
||||||
|
|
||||||
/// This changes what IR we emit when we translate an unpredictable instruction.
|
|
||||||
/// If this is false, the ExceptionRaised IR instruction is emitted.
|
|
||||||
/// If this is true, we define some behaviour for some instructions.
|
|
||||||
bool define_unpredictable_behaviour = false;
|
|
||||||
|
|
||||||
/// This changes what IR we emit when we translate a hint instruction.
|
|
||||||
/// If this is false, we treat the instruction as a NOP.
|
|
||||||
/// If this is true, we emit an ExceptionRaised instruction.
|
|
||||||
bool hook_hint_instructions = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function translates instructions in memory into our intermediate representation.
|
* This function translates instructions in memory into our intermediate representation.
|
||||||
* @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c.
|
* @param descriptor The starting location of the basic block. Includes information like PC, Thumb state, &c.
|
||||||
* @param tcb The callbacks we should use to read emulated memory.
|
* @param tcb The callbacks we should use to read emulated memory.
|
||||||
* @param options Configures how certain instructions are translated.
|
* @param conf Configures how certain instructions are translated.
|
||||||
* @return A translated basic block in the intermediate representation.
|
* @return A translated basic block in the intermediate representation.
|
||||||
*/
|
*/
|
||||||
void Translate(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options);
|
void Translate(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function translates a single provided instruction into our intermediate representation.
|
* This function translates a single provided instruction into our intermediate representation.
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
* Copyright (c) 2016 MerryMage
|
* Copyright (c) 2016 MerryMage
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
@@ -10,7 +13,7 @@ namespace Dynarmic::A32 {
|
|||||||
|
|
||||||
// BKPT #<imm16>
|
// BKPT #<imm16>
|
||||||
bool TranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) {
|
bool TranslatorVisitor::arm_BKPT(Cond cond, Imm<12> /*imm12*/, Imm<4> /*imm4*/) {
|
||||||
if (cond != Cond::AL && !options.define_unpredictable_behaviour) {
|
if (cond != Cond::AL && !conf.define_unpredictable_behaviour) {
|
||||||
return UnpredictableInstruction();
|
return UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
// UNPREDICTABLE: The instruction executes conditionally.
|
// UNPREDICTABLE: The instruction executes conditionally.
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "common/assert.h"
|
#include "common/assert.h"
|
||||||
|
#include "dynarmic/interface/A32/config.h"
|
||||||
#include "dynarmic/mcl/bit.hpp"
|
#include "dynarmic/mcl/bit.hpp"
|
||||||
|
|
||||||
#include "dynarmic/frontend/A32/a32_ir_emitter.h"
|
#include "dynarmic/frontend/A32/a32_ir_emitter.h"
|
||||||
@@ -25,12 +26,14 @@ enum class Exception;
|
|||||||
struct TranslatorVisitor final {
|
struct TranslatorVisitor final {
|
||||||
using instruction_return_type = bool;
|
using instruction_return_type = bool;
|
||||||
|
|
||||||
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const TranslationOptions& options)
|
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf)
|
||||||
: ir(block, descriptor, options.arch_version), options(options) {}
|
: ir(block, descriptor, conf.arch_version)
|
||||||
|
, conf(conf)
|
||||||
|
{}
|
||||||
|
|
||||||
A32::IREmitter ir;
|
A32::IREmitter ir;
|
||||||
ConditionalState cond_state = ConditionalState::None;
|
ConditionalState cond_state = ConditionalState::None;
|
||||||
TranslationOptions options;
|
A32::UserConfig const& conf;
|
||||||
|
|
||||||
size_t current_instruction_size;
|
size_t current_instruction_size;
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
* Copyright (c) 2019 MerryMage
|
* Copyright (c) 2019 MerryMage
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
@@ -9,7 +12,7 @@
|
|||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_PLD_imm(bool /*add*/, bool R, Reg /*n*/, Imm<12> /*imm12*/) {
|
bool TranslatorVisitor::arm_PLD_imm(bool /*add*/, bool R, Reg /*n*/, Imm<12> /*imm12*/) {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +21,7 @@ bool TranslatorVisitor::arm_PLD_imm(bool /*add*/, bool R, Reg /*n*/, Imm<12> /*i
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_PLD_reg(bool /*add*/, bool R, Reg /*n*/, Imm<5> /*imm5*/, ShiftType /*shift*/, Reg /*m*/) {
|
bool TranslatorVisitor::arm_PLD_reg(bool /*add*/, bool R, Reg /*n*/, Imm<5> /*imm5*/, ShiftType /*shift*/, Reg /*m*/) {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,7 +30,7 @@ bool TranslatorVisitor::arm_PLD_reg(bool /*add*/, bool R, Reg /*n*/, Imm<5> /*im
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_SEV() {
|
bool TranslatorVisitor::arm_SEV() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -35,7 +38,7 @@ bool TranslatorVisitor::arm_SEV() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_SEVL() {
|
bool TranslatorVisitor::arm_SEVL() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +46,7 @@ bool TranslatorVisitor::arm_SEVL() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_WFE() {
|
bool TranslatorVisitor::arm_WFE() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +54,7 @@ bool TranslatorVisitor::arm_WFE() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_WFI() {
|
bool TranslatorVisitor::arm_WFI() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +62,7 @@ bool TranslatorVisitor::arm_WFI() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::arm_YIELD() {
|
bool TranslatorVisitor::arm_YIELD() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -642,7 +642,7 @@ bool TranslatorVisitor::thumb16_SUB_sp(Imm<7> imm7) {
|
|||||||
|
|
||||||
// SEV<c>
|
// SEV<c>
|
||||||
bool TranslatorVisitor::thumb16_SEV() {
|
bool TranslatorVisitor::thumb16_SEV() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::SendEvent);
|
return RaiseException(Exception::SendEvent);
|
||||||
@@ -650,7 +650,7 @@ bool TranslatorVisitor::thumb16_SEV() {
|
|||||||
|
|
||||||
// SEVL<c>
|
// SEVL<c>
|
||||||
bool TranslatorVisitor::thumb16_SEVL() {
|
bool TranslatorVisitor::thumb16_SEVL() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::SendEventLocal);
|
return RaiseException(Exception::SendEventLocal);
|
||||||
@@ -658,7 +658,7 @@ bool TranslatorVisitor::thumb16_SEVL() {
|
|||||||
|
|
||||||
// WFE<c>
|
// WFE<c>
|
||||||
bool TranslatorVisitor::thumb16_WFE() {
|
bool TranslatorVisitor::thumb16_WFE() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::WaitForEvent);
|
return RaiseException(Exception::WaitForEvent);
|
||||||
@@ -666,7 +666,7 @@ bool TranslatorVisitor::thumb16_WFE() {
|
|||||||
|
|
||||||
// WFI<c>
|
// WFI<c>
|
||||||
bool TranslatorVisitor::thumb16_WFI() {
|
bool TranslatorVisitor::thumb16_WFI() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::WaitForInterrupt);
|
return RaiseException(Exception::WaitForInterrupt);
|
||||||
@@ -674,7 +674,7 @@ bool TranslatorVisitor::thumb16_WFI() {
|
|||||||
|
|
||||||
// YIELD<c>
|
// YIELD<c>
|
||||||
bool TranslatorVisitor::thumb16_YIELD() {
|
bool TranslatorVisitor::thumb16_YIELD() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::Yield);
|
return RaiseException(Exception::Yield);
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
* Copyright (c) 2021 MerryMage
|
* Copyright (c) 2021 MerryMage
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
@@ -8,7 +11,7 @@
|
|||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
static bool PLDHandler(TranslatorVisitor& v, bool W) {
|
static bool PLDHandler(TranslatorVisitor& v, bool W) {
|
||||||
if (!v.options.hook_hint_instructions) {
|
if (!v.conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -18,7 +21,7 @@ static bool PLDHandler(TranslatorVisitor& v, bool W) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool PLIHandler(TranslatorVisitor& v) {
|
static bool PLIHandler(TranslatorVisitor& v) {
|
||||||
if (!v.options.hook_hint_instructions) {
|
if (!v.conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,10 +22,12 @@
|
|||||||
|
|
||||||
namespace Dynarmic::A32 {
|
namespace Dynarmic::A32 {
|
||||||
|
|
||||||
void TranslateArm(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) {
|
void TranslateArm(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf) {
|
||||||
const bool single_step = descriptor.SingleStepping();
|
const bool single_step = descriptor.SingleStepping();
|
||||||
TranslatorVisitor visitor{block, descriptor, options};
|
TranslatorVisitor visitor{block, descriptor, conf};
|
||||||
bool should_continue = true;
|
bool should_continue = true;
|
||||||
|
|
||||||
|
auto tcb = conf.callbacks;
|
||||||
do {
|
do {
|
||||||
const u32 arm_pc = visitor.ir.current_location.PC();
|
const u32 arm_pc = visitor.ir.current_location.PC();
|
||||||
u64 ticks_for_instruction = 1;
|
u64 ticks_for_instruction = 1;
|
||||||
|
|||||||
@@ -103,10 +103,12 @@ inline bool MaybeVFPOrASIMDInstruction(u32 thumb_instruction) noexcept {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, TranslateCallbacks* tcb, const TranslationOptions& options) {
|
void TranslateThumb(IR::Block& block, LocationDescriptor descriptor, const A32::UserConfig& conf) {
|
||||||
const bool single_step = descriptor.SingleStepping();
|
const bool single_step = descriptor.SingleStepping();
|
||||||
TranslatorVisitor visitor{block, descriptor, options};
|
TranslatorVisitor visitor{block, descriptor, conf};
|
||||||
bool should_continue = true;
|
bool should_continue = true;
|
||||||
|
|
||||||
|
auto tcb = conf.callbacks;
|
||||||
do {
|
do {
|
||||||
const u32 arm_pc = visitor.ir.current_location.PC();
|
const u32 arm_pc = visitor.ir.current_location.PC();
|
||||||
u64 ticks_for_instruction = 1;
|
u64 ticks_for_instruction = 1;
|
||||||
|
|||||||
@@ -11,19 +11,20 @@
|
|||||||
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
#include "dynarmic/frontend/A64/a64_location_descriptor.h"
|
||||||
#include "dynarmic/frontend/A64/decoder/a64.h"
|
#include "dynarmic/frontend/A64/decoder/a64.h"
|
||||||
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
#include "dynarmic/frontend/A64/translate/impl/impl.h"
|
||||||
|
#include "dynarmic/interface/A64/config.h"
|
||||||
#include "dynarmic/ir/basic_block.h"
|
#include "dynarmic/ir/basic_block.h"
|
||||||
#include "dynarmic/ir/terminal.h"
|
#include "dynarmic/ir/terminal.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
void Translate(IR::Block& block, LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, TranslationOptions options) {
|
void Translate(IR::Block& block, LocationDescriptor descriptor, A64::UserConfig const& conf) {
|
||||||
const bool single_step = descriptor.SingleStepping();
|
const bool single_step = descriptor.SingleStepping();
|
||||||
TranslatorVisitor visitor{block, descriptor, std::move(options)};
|
TranslatorVisitor visitor{block, descriptor, conf};
|
||||||
|
|
||||||
bool should_continue = true;
|
bool should_continue = true;
|
||||||
do {
|
do {
|
||||||
const u64 pc = visitor.ir.current_location->PC();
|
const u64 pc = visitor.ir.current_location->PC();
|
||||||
if (const auto instruction = memory_read_code(pc)) {
|
if (const auto instruction = conf.callbacks->MemoryReadCode(pc)) {
|
||||||
if (auto decoder = Decode<TranslatorVisitor, bool>(visitor, *instruction)) {
|
if (auto decoder = Decode<TranslatorVisitor, bool>(visitor, *instruction)) {
|
||||||
should_continue = *decoder;
|
should_continue = *decoder;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
|
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "dynarmic/interface/A64/config.h"
|
||||||
|
|
||||||
namespace Dynarmic {
|
namespace Dynarmic {
|
||||||
|
|
||||||
@@ -22,32 +23,14 @@ namespace A64 {
|
|||||||
|
|
||||||
class LocationDescriptor;
|
class LocationDescriptor;
|
||||||
|
|
||||||
using MemoryReadCodeFuncType = std::function<std::optional<u32>(u64 vaddr)>;
|
|
||||||
|
|
||||||
struct TranslationOptions {
|
|
||||||
/// This changes what IR we emit when we translate an unpredictable instruction.
|
|
||||||
/// If this is false, the ExceptionRaised IR instruction is emitted.
|
|
||||||
/// If this is true, we define some behaviour for some instructions.
|
|
||||||
bool define_unpredictable_behaviour = false;
|
|
||||||
|
|
||||||
/// This tells the translator a wall clock will be used, thus allowing it
|
|
||||||
/// to avoid writting certain unnecessary code only needed for cycle timers.
|
|
||||||
bool wall_clock_cntpct = false;
|
|
||||||
|
|
||||||
/// This changes what IR we emit when we translate a hint instruction.
|
|
||||||
/// If this is false, we treat the instruction as a NOP.
|
|
||||||
/// If this is true, we emit an ExceptionRaised instruction.
|
|
||||||
bool hook_hint_instructions = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function translates instructions in memory into our intermediate representation.
|
* This function translates instructions in memory into our intermediate representation.
|
||||||
* @param descriptor The starting location of the basic block. Includes information like PC, FPCR state, &c.
|
* @param descriptor The starting location of the basic block. Includes information like PC, FPCR state, &c.
|
||||||
* @param memory_read_code The function we should use to read emulated memory.
|
* @param memory_read_code The function we should use to read emulated memory.
|
||||||
* @param options Configures how certain instructions are translated.
|
* @param conf Configures how certain instructions are translated.
|
||||||
* @return A translated basic block in the intermediate representation.
|
* @return A translated basic block in the intermediate representation.
|
||||||
*/
|
*/
|
||||||
void Translate(IR::Block& block, LocationDescriptor descriptor, MemoryReadCodeFuncType memory_read_code, TranslationOptions options);
|
void Translate(IR::Block& block, LocationDescriptor descriptor, A64::UserConfig const& conf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function translates a single provided instruction into our intermediate representation.
|
* This function translates a single provided instruction into our intermediate representation.
|
||||||
|
|||||||
@@ -15,17 +15,20 @@
|
|||||||
#include "dynarmic/frontend/A64/a64_types.h"
|
#include "dynarmic/frontend/A64/a64_types.h"
|
||||||
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
#include "dynarmic/frontend/A64/translate/a64_translate.h"
|
||||||
#include "dynarmic/frontend/imm.h"
|
#include "dynarmic/frontend/imm.h"
|
||||||
|
#include "dynarmic/interface/A64/config.h"
|
||||||
|
|
||||||
namespace Dynarmic::A64 {
|
namespace Dynarmic::A64 {
|
||||||
|
|
||||||
struct TranslatorVisitor final {
|
struct TranslatorVisitor final {
|
||||||
using instruction_return_type = bool;
|
using instruction_return_type = bool;
|
||||||
|
|
||||||
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, TranslationOptions options)
|
explicit TranslatorVisitor(IR::Block& block, LocationDescriptor descriptor, A64::UserConfig const& conf)
|
||||||
: ir(block, descriptor), options(std::move(options)) {}
|
: ir(block, descriptor)
|
||||||
|
, conf(conf)
|
||||||
|
{}
|
||||||
|
|
||||||
A64::IREmitter ir;
|
A64::IREmitter ir;
|
||||||
TranslationOptions options;
|
A64::UserConfig const& conf;
|
||||||
|
|
||||||
bool UnpredictableInstruction();
|
bool UnpredictableInstruction();
|
||||||
bool DecodeError();
|
bool DecodeError();
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
/* This file is part of the dynarmic project.
|
/* This file is part of the dynarmic project.
|
||||||
* Copyright (c) 2018 MerryMage
|
* Copyright (c) 2018 MerryMage
|
||||||
* SPDX-License-Identifier: 0BSD
|
* SPDX-License-Identifier: 0BSD
|
||||||
@@ -25,7 +28,7 @@ static bool ExclusiveSharedDecodeAndOperation(TranslatorVisitor& v, bool pair, s
|
|||||||
if (memop == IR::MemOp::LOAD && pair && Rt == *Rt2) {
|
if (memop == IR::MemOp::LOAD && pair && Rt == *Rt2) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
} else if (memop == IR::MemOp::STORE && (*Rs == Rt || (pair && *Rs == *Rt2))) {
|
} else if (memop == IR::MemOp::STORE && (*Rs == Rt || (pair && *Rs == *Rt2))) {
|
||||||
if (!v.options.define_unpredictable_behaviour) {
|
if (!v.conf.define_unpredictable_behaviour) {
|
||||||
return v.UnpredictableInstruction();
|
return v.UnpredictableInstruction();
|
||||||
}
|
}
|
||||||
// UNPREDICTABLE: The Constraint_NONE case is executed.
|
// UNPREDICTABLE: The Constraint_NONE case is executed.
|
||||||
|
|||||||
@@ -42,35 +42,35 @@ bool TranslatorVisitor::NOP() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::YIELD() {
|
bool TranslatorVisitor::YIELD() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::Yield);
|
return RaiseException(Exception::Yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::WFE() {
|
bool TranslatorVisitor::WFE() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::WaitForEvent);
|
return RaiseException(Exception::WaitForEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::WFI() {
|
bool TranslatorVisitor::WFI() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::WaitForInterrupt);
|
return RaiseException(Exception::WaitForInterrupt);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::SEV() {
|
bool TranslatorVisitor::SEV() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::SendEvent);
|
return RaiseException(Exception::SendEvent);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TranslatorVisitor::SEVL() {
|
bool TranslatorVisitor::SEVL() {
|
||||||
if (!options.hook_hint_instructions) {
|
if (!conf.hook_hint_instructions) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return RaiseException(Exception::SendEventLocal);
|
return RaiseException(Exception::SendEventLocal);
|
||||||
@@ -129,7 +129,7 @@ bool TranslatorVisitor::MRS(Imm<1> o0, Imm<3> op1, Imm<4> CRn, Imm<4> CRm, Imm<3
|
|||||||
return true;
|
return true;
|
||||||
case SystemRegisterEncoding::CNTPCT_EL0:
|
case SystemRegisterEncoding::CNTPCT_EL0:
|
||||||
// HACK: Ensure that this is the first instruction in the block it's emitted in, so the cycle count is most up-to-date.
|
// HACK: Ensure that this is the first instruction in the block it's emitted in, so the cycle count is most up-to-date.
|
||||||
if (!ir.block.instructions.empty() && !options.wall_clock_cntpct) {
|
if (!ir.block.instructions.empty() && !conf.wall_clock_cntpct) {
|
||||||
ir.block.CycleCount()--;
|
ir.block.CycleCount()--;
|
||||||
ir.SetTerm(IR::Term::LinkBlock{*ir.current_location});
|
ir.SetTerm(IR::Term::LinkBlock{*ir.current_location});
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ static void RunInstance(size_t run_number, ThumbTestEnv& test_env, A32::UserConf
|
|||||||
while (num_insts < instructions_to_execute_count) {
|
while (num_insts < instructions_to_execute_count) {
|
||||||
A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, A32::FPSCR{}};
|
A32::LocationDescriptor descriptor = {u32(num_insts * 4), cpsr, A32::FPSCR{}};
|
||||||
ir_block.Reset(descriptor);
|
ir_block.Reset(descriptor);
|
||||||
A32::Translate(ir_block, descriptor, &test_env, {});
|
A32::Translate(ir_block, descriptor, config);
|
||||||
Optimization::Optimize(ir_block, config, {});
|
Optimization::Optimize(ir_block, config, {});
|
||||||
printf("\n\nIR:\n%s", IR::DumpBlock(ir_block).c_str());
|
printf("\n\nIR:\n%s", IR::DumpBlock(ir_block).c_str());
|
||||||
printf("\n\nx86_64:\n");
|
printf("\n\nx86_64:\n");
|
||||||
|
|||||||
@@ -268,7 +268,7 @@ static void RunTestInstance(Dynarmic::A64::Jit& jit, A64Unicorn& uni, A64TestEnv
|
|||||||
// const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); };
|
// const auto get_code = [&jit_env](u64 vaddr) { return jit_env.MemoryReadCode(vaddr); };
|
||||||
// const A64::LocationDescriptor location{instructions_start, FP::FPCR{fpcr}};
|
// const A64::LocationDescriptor location{instructions_start, FP::FPCR{fpcr}};
|
||||||
// IR::Block ir_block{location};
|
// IR::Block ir_block{location};
|
||||||
// A64::Translate(ir_block, location, get_code, {});
|
// A64::Translate(ir_block, location, config);
|
||||||
// fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block));
|
// fmt::print("IR:\n{}\n", IR::DumpBlock(ir_block));
|
||||||
// Optimization::Optimize(ir_block, conf, {});
|
// Optimization::Optimize(ir_block, conf, {});
|
||||||
// fmt::print("Optimized IR:\n{}\n", IR::DumpBlock(ir_block));
|
// fmt::print("Optimized IR:\n{}\n", IR::DumpBlock(ir_block));
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ li.checked::marker { content: "\2612"; }
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="labelLinks">
|
<widget class="QLabel" name="labelLinks">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string><html><head/><body><p><a href="https://eden-emulator.github.io/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.eden-emu.dev"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/activity/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://discord.gg/HstXbPch7X"><span style=" text-decoration: underline; color:#039be5;">Discord</span></a> | <a href="https://stt.gg/qKgFEAbH"><span style=" text-decoration: underline; color:#039be5;">Stoat</span></a> | <a href="https://nitter.poast.org/edenemuofficial"><span style=" text-decoration: underline; color:#039be5;">Twitter</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></string>
|
<string><html><head/><body><p><a href="https://eden-emulator.github.io/"><span style=" text-decoration: underline; color:#039be5;">Website</span></a> | <a href="https://git.eden-emu.dev"><span style=" text-decoration: underline; color:#039be5;">Source Code</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/activity/contributors"><span style=" text-decoration: underline; color:#039be5;">Contributors</span></a> | <a href="https://discord.gg/HstXbPch7X"><span style=" text-decoration: underline; color:#039be5;">Discord</span></a> | <a href="https://stt.gg/qKgFEAbH"><span style=" text-decoration: underline; color:#039be5;">Stoat</span></a> | <a href="https://x.com/edenemuofficial"><span style=" text-decoration: underline; color:#039be5;">Twitter</span></a> | <a href="https://git.eden-emu.dev/eden-emu/eden/src/branch/master/LICENSE.txt"><span style=" text-decoration: underline; color:#039be5;">License</span></a></p></body></html></string>
|
||||||
</property>
|
</property>
|
||||||
<property name="openExternalLinks">
|
<property name="openExternalLinks">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
|
|||||||
@@ -131,7 +131,8 @@ GRenderWindow::GRenderWindow(MainWindow* parent,
|
|||||||
strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland") ||
|
strict_context_required = QGuiApplication::platformName() == QStringLiteral("wayland") ||
|
||||||
QGuiApplication::platformName() == QStringLiteral("wayland-egl");
|
QGuiApplication::platformName() == QStringLiteral("wayland-egl");
|
||||||
|
|
||||||
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &MainWindow::OnLoadComplete);
|
connect(this, &GRenderWindow::FirstFrameDisplayed, parent, &MainWindow::OnLoadComplete,
|
||||||
|
Qt::QueuedConnection);
|
||||||
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &MainWindow::OnExecuteProgram,
|
connect(this, &GRenderWindow::ExecuteProgramSignal, parent, &MainWindow::OnExecuteProgram,
|
||||||
Qt::QueuedConnection);
|
Qt::QueuedConnection);
|
||||||
connect(this, &GRenderWindow::ExitSignal, parent, &MainWindow::OnExit, Qt::QueuedConnection);
|
connect(this, &GRenderWindow::ExitSignal, parent, &MainWindow::OnExit, Qt::QueuedConnection);
|
||||||
|
|||||||
@@ -3147,6 +3147,10 @@ bool MainWindow::ConfirmShutdownGame() {
|
|||||||
|
|
||||||
void MainWindow::OnLoadComplete() {
|
void MainWindow::OnLoadComplete() {
|
||||||
loading_screen->OnLoadComplete();
|
loading_screen->OnLoadComplete();
|
||||||
|
if (emulation_running) {
|
||||||
|
render_window->show();
|
||||||
|
render_window->setFocus();
|
||||||
|
}
|
||||||
|
|
||||||
perf_overlay = new PerformanceOverlay(this);
|
perf_overlay = new PerformanceOverlay(this);
|
||||||
perf_overlay->setVisible(ui->action_Show_Performance_Overlay->isChecked());
|
perf_overlay->setVisible(ui->action_Show_Performance_Overlay->isChecked());
|
||||||
|
|||||||
Reference in New Issue
Block a user