diff --git a/src/SharpEmu.CLI/Program.cs b/src/SharpEmu.CLI/Program.cs index 9f406d2..0707bb3 100644 --- a/src/SharpEmu.CLI/Program.cs +++ b/src/SharpEmu.CLI/Program.cs @@ -1000,7 +1000,7 @@ internal static partial class Program private static void PrintUsage() { - Log.Info("Usage: SharpEmu.CLI [--strict] [--trace-imports[=N]] [--cpu-engine=] [--log-level=] [--log-file[=]] [--window-mode=] [--resolution=] [--display=] [--refresh-rate=] [--scaling=] [--vsync=] [--hdr=] [--overlay=] [--overlay-mode=] [--overlay-corner=] [--debug-server[=host:port]] "); + Log.Info("Usage: SharpEmu.CLI [--strict] [--trace-imports[=N]] [--cpu-engine=] [--console=] [--console-language=] [--log-level=] [--log-file[=]] [--window-mode=] [--resolution=] [--display=] [--refresh-rate=] [--scaling=] [--vsync=] [--hdr=] [--overlay=] [--overlay-mode=] [--overlay-corner=] [--debug-server[=host:port]] "); Log.Info(@"Example: SharpEmu.CLI --cpu-engine=native --trace-imports=64 --log-level=debug --log-file ""E:\Games\...\eboot.bin"""); Log.Info("Debug server: --debug-server starts a live debug listener (default 127.0.0.1:5714); connect with SharpEmu.DebugClient."); } @@ -1062,6 +1062,7 @@ internal static partial class Program var strictDynlibResolution = false; var importTraceLimit = 0; var cpuEngine = CpuExecutionEngine.NativeOnly; + var systemLanguage = 1; HostWindowMode? windowModeOverride = null; HostScalingMode? scalingModeOverride = null; int? windowWidthOverride = null; @@ -1080,6 +1081,26 @@ internal static partial class Program for (var i = 0; i < args.Length; i++) { var argument = args[i]; + if (TrySplitOption(argument, "--console", out var consoleText)) + { + if (!string.Equals(consoleText, "ps5", StringComparison.OrdinalIgnoreCase)) + { + ebootPath = string.Empty; + runtimeOptions = default; + return false; + } + continue; + } + if (TrySplitOption(argument, "--console-language", out var consoleLanguageText)) + { + if (!TryParseSystemLanguage(consoleLanguageText, out systemLanguage)) + { + ebootPath = string.Empty; + runtimeOptions = default; + return false; + } + continue; + } if (TrySplitOption(argument, "--window-mode", out var windowModeText)) { if (!TryParseWindowMode(windowModeText, out var windowMode)) @@ -1351,6 +1372,7 @@ internal static partial class Program runtimeOptions = new SharpEmuRuntimeOptions { CpuEngine = cpuEngine, + SystemLanguage = systemLanguage, StrictDynlibResolution = strictDynlibResolution, ImportTraceLimit = importTraceLimit, }; @@ -1445,6 +1467,46 @@ internal static partial class Program return Enum.IsDefined(mode); } + private static bool TryParseSystemLanguage(string value, out int language) + { + language = value.ToLowerInvariant() switch + { + "japanese" => 0, + "englishus" => 1, + "french" => 2, + "spanishspain" => 3, + "german" => 4, + "italian" => 5, + "dutch" => 6, + "portugueseportugal" => 7, + "russian" => 8, + "korean" => 9, + "chinesetraditional" => 10, + "chinesesimplified" => 11, + "finnish" => 12, + "swedish" => 13, + "danish" => 14, + "norwegian" => 15, + "polish" => 16, + "portuguesebrazil" => 17, + "englishuk" => 18, + "turkish" => 19, + "spanishlatinamerica" => 20, + "arabic" => 21, + "frenchcanada" => 22, + "czech" => 23, + "hungarian" => 24, + "greek" => 25, + "romanian" => 26, + "thai" => 27, + "vietnamese" => 28, + "indonesian" => 29, + "ukrainian" => 30, + _ => -1, + }; + return language >= 0; + } + private static bool TryParseScalingMode(string value, out HostScalingMode mode) { mode = value.ToLowerInvariant() switch diff --git a/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs b/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs index 41022d2..51ba9a3 100644 --- a/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs +++ b/src/SharpEmu.Core/Runtime/SharpEmuRuntime.cs @@ -42,6 +42,7 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime private readonly CpuExecutionOptions _cpuExecutionOptions; private readonly IFileSystem _fileSystem; private readonly GuestGpuMemory? _gpuMemory; + private readonly int _systemLanguage; private readonly object _dynamicModuleGate = new(); private bool _disposed; @@ -63,7 +64,8 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime ISymbolCatalog? symbolCatalog = null, CpuExecutionOptions cpuExecutionOptions = default, IFileSystem? fileSystem = null, - GuestGpuMemory? gpuMemory = null) + GuestGpuMemory? gpuMemory = null, + int systemLanguage = 1) { _gpuMemory = gpuMemory; _selfLoader = selfLoader ?? throw new ArgumentNullException(nameof(selfLoader)); @@ -79,6 +81,7 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime DebugHook = cpuExecutionOptions.DebugHook, }; _fileSystem = fileSystem ?? new PhysicalFileSystem(); + _systemLanguage = systemLanguage; } public static ISharpEmuRuntime CreateDefault(SharpEmuRuntimeOptions options = default) @@ -112,7 +115,8 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime Aerolib.Instance, cpuExecutionOptions, fileSystem, - gpuMemory); + gpuMemory, + options.SystemLanguage ?? 1); } public SelfImage LoadImage(string ebootPath) @@ -160,7 +164,7 @@ public sealed class SharpEmuRuntime : ISharpEmuRuntime VideoOutExports.ConfigureApplicationInfo(image.Title, image.TitleId, image.Version); KernelMemoryCompatExports.ConfigureApplicationInfo(image.TitleId); SaveDataExports.ConfigureApplicationInfo(image.TitleId); - SystemServiceExports.ConfigureApplicationInfo(image.TitleId); + SystemServiceExports.ConfigureApplicationInfo(image.TitleId, _systemLanguage); _ = RegisterLoadedModule(normalizedEbootPath, image, isMain: true, isSystemModule: false); KernelRuntimeCompatExports.ConfigureProcessProcParamAddress(image.ProcParamAddress); Console.Error.WriteLine($"[RUNTIME] Entry: 0x{image.EntryPoint:X16}"); diff --git a/src/SharpEmu.Core/Runtime/SharpEmuRuntimeOptions.cs b/src/SharpEmu.Core/Runtime/SharpEmuRuntimeOptions.cs index de9adf8..3fdc705 100644 --- a/src/SharpEmu.Core/Runtime/SharpEmuRuntimeOptions.cs +++ b/src/SharpEmu.Core/Runtime/SharpEmuRuntimeOptions.cs @@ -10,6 +10,8 @@ public readonly struct SharpEmuRuntimeOptions { public CpuExecutionEngine CpuEngine { get; init; } + public int? SystemLanguage { get; init; } + public bool StrictDynlibResolution { get; init; } public int ImportTraceLimit { get; init; } diff --git a/src/SharpEmu.GUI/GuiSettings.cs b/src/SharpEmu.GUI/GuiSettings.cs index 1a8447a..52a04b2 100644 --- a/src/SharpEmu.GUI/GuiSettings.cs +++ b/src/SharpEmu.GUI/GuiSettings.cs @@ -54,6 +54,10 @@ public sealed class GuiSettings /// UI language, matching a file code under Languages/ (e.g. "en", "tr"). public string Language { get; set; } = "en"; + public string ConsoleType { get; set; } = "PS5"; + + public string ConsoleLanguage { get; set; } = "EnglishUS"; + /// Default text-entry profile exposed to games. public string DefaultProfile { get; set; } = "Sharp"; @@ -144,6 +148,40 @@ public sealed class GuiSettings legacyProfile is { Length: 2 } ? legacyProfile[1] : settings.DefaultProfile); settings.DiscordClientId ??= "1525606762248540221"; settings.LibraryLayout = NormalizeChoice(settings.LibraryLayout, "Carousel", "Grid"); + settings.ConsoleType = NormalizeChoice(settings.ConsoleType, "PS5"); + settings.ConsoleLanguage = NormalizeChoice( + settings.ConsoleLanguage, + "EnglishUS", + "Japanese", + "French", + "SpanishSpain", + "German", + "Italian", + "Dutch", + "PortuguesePortugal", + "Russian", + "Korean", + "ChineseTraditional", + "ChineseSimplified", + "Finnish", + "Swedish", + "Danish", + "Norwegian", + "Polish", + "PortugueseBrazil", + "EnglishUK", + "Turkish", + "SpanishLatinAmerica", + "Arabic", + "FrenchCanada", + "Czech", + "Hungarian", + "Greek", + "Romanian", + "Thai", + "Vietnamese", + "Indonesian", + "Ukrainian"); settings.WindowMode = NormalizeChoice(settings.WindowMode, "Windowed", "Borderless", "Exclusive"); settings.Resolution = NormalizeResolution(settings.Resolution); settings.ScalingMode = NormalizeChoice(settings.ScalingMode, "Fit", "Cover", "Stretch", "Integer"); diff --git a/src/SharpEmu.GUI/Languages/ar.json b/src/SharpEmu.GUI/Languages/ar.json index 7120751..7fb3f3a 100644 --- a/src/SharpEmu.GUI/Languages/ar.json +++ b/src/SharpEmu.GUI/Languages/ar.json @@ -205,6 +205,11 @@ "Updater.Status.ChecksumFailed": "فشل التحديث المنزَّل في اجتياز تحقق SHA-256.", "Updater.Status.Unsupported": "يتطلب التحديث التلقائي إصدار x64 لنظام Windows أو Linux أو macOS.", "Options.Graphics": "الرسومات", + + "Options.Console.Type.Label": "وحدة التحكم", + "Options.Console.Type.Desc": "طراز وحدة التحكم الذي يتم إبلاغ الألعاب به.", + "Options.Console.Language.Label": "لغة وحدة التحكم", + "Options.Console.Language.Desc": "لغة النظام التي يتم إبلاغ الألعاب بها.", "Options.Section.Rendering": "التصيير", "Options.Section.Display": "العرض", "Options.WindowMode.Label": "وضع النافذة", diff --git a/src/SharpEmu.GUI/Languages/az.json b/src/SharpEmu.GUI/Languages/az.json index 626c6ec..bbaf5b2 100644 --- a/src/SharpEmu.GUI/Languages/az.json +++ b/src/SharpEmu.GUI/Languages/az.json @@ -59,6 +59,11 @@ "Options.Section.Display": "Ekran", "Options.Graphics": "Qrafika", + "Options.Console.Type.Label": "Konsol", + "Options.Console.Type.Desc": "Oyunlara bildirilən konsol modeli.", + "Options.Console.Language.Label": "Konsol dili", + "Options.Console.Language.Desc": "Oyunlara bildirilən sistem dili.", + "Options.RenderResolution.Label": "Daxili təsvir ölçüsü", "Options.RenderResolution.Desc": "Ekrandan kənar təsvir hədəflərini ilkin ölçüdən aşağı ölçüdə yaradıb göstərərkən böyüdün. Aşağı dəyərlər təsvir keyfiyyətini azaldaraq GPU yükünü yüngülləşdirir; növbəti işə salınmada qüvvəyə minir.", "Options.RenderResolution.Native": "100% (ilkin)", diff --git a/src/SharpEmu.GUI/Languages/br.json b/src/SharpEmu.GUI/Languages/br.json index 0debf2b..b4e0e08 100644 --- a/src/SharpEmu.GUI/Languages/br.json +++ b/src/SharpEmu.GUI/Languages/br.json @@ -206,6 +206,11 @@ "Updater.Status.ChecksumFailed": "A atualização baixada falhou na verificação SHA-256.", "Updater.Status.Unsupported": "A atualização automática requer um build x64 para Windows, Linux ou macOS.", "Options.Graphics": "Gráficos", + + "Options.Console.Type.Label": "Console", + "Options.Console.Type.Desc": "Modelo de console informado aos jogos.", + "Options.Console.Language.Label": "Idioma do console", + "Options.Console.Language.Desc": "Idioma do sistema informado aos jogos.", "Options.Section.Rendering": "RENDERIZAÇÃO", "Options.Section.Display": "TELA", "Options.WindowMode.Label": "Modo de janela", diff --git a/src/SharpEmu.GUI/Languages/de.json b/src/SharpEmu.GUI/Languages/de.json index c3a4189..4e5e83f 100644 --- a/src/SharpEmu.GUI/Languages/de.json +++ b/src/SharpEmu.GUI/Languages/de.json @@ -205,6 +205,11 @@ "Updater.Status.ChecksumFailed": "Das heruntergeladene Update hat die SHA-256-Prüfung nicht bestanden.", "Updater.Status.Unsupported": "Automatische Updates erfordern einen x64-Build für Windows, Linux oder macOS.", "Options.Graphics": "Grafik", + + "Options.Console.Type.Label": "Konsole", + "Options.Console.Type.Desc": "Konsolenmodell, das Spielen gemeldet wird.", + "Options.Console.Language.Label": "Konsolensprache", + "Options.Console.Language.Desc": "Systemsprache, die Spielen gemeldet wird.", "Options.Section.Rendering": "DARSTELLUNG", "Options.Section.Display": "ANZEIGE", "Options.WindowMode.Label": "Fenstermodus", diff --git a/src/SharpEmu.GUI/Languages/dk.json b/src/SharpEmu.GUI/Languages/dk.json index 88d7658..13a6654 100644 --- a/src/SharpEmu.GUI/Languages/dk.json +++ b/src/SharpEmu.GUI/Languages/dk.json @@ -205,6 +205,11 @@ "Updater.Status.ChecksumFailed": "Den downloadede opdatering bestod ikke SHA-256-verifikationen.", "Updater.Status.Unsupported": "Automatisk opdatering kræver et x64-build til Windows, Linux eller macOS.", "Options.Graphics": "Grafik", + + "Options.Console.Type.Label": "Konsol", + "Options.Console.Type.Desc": "Konsolmodel der rapporteres til spil.", + "Options.Console.Language.Label": "Konsolsprog", + "Options.Console.Language.Desc": "Systemsprog der rapporteres til spil.", "Options.Section.Rendering": "GENGIVELSE", "Options.Section.Display": "SKÆRM", "Options.WindowMode.Label": "Vinduestilstand", diff --git a/src/SharpEmu.GUI/Languages/ee.json b/src/SharpEmu.GUI/Languages/ee.json index 10c414d..48af79d 100644 --- a/src/SharpEmu.GUI/Languages/ee.json +++ b/src/SharpEmu.GUI/Languages/ee.json @@ -73,6 +73,11 @@ "Options.Section.Display": "KUVA", "Options.Graphics": "Graafika", + "Options.Console.Type.Label": "Konsool", + "Options.Console.Type.Desc": "Mängudele teatatud konsoolimudel.", + "Options.Console.Language.Label": "Konsooli keel", + "Options.Console.Language.Desc": "Mängudele teatatud süsteemikeel.", + "Options.WindowMode.Label": "Aknarežiim", "Options.WindowMode.Desc": "Tavaline aken, äärteta töölauavaade või eksklusiivne täisekraan.", "Options.WindowMode.Windowed": "Aken", diff --git a/src/SharpEmu.GUI/Languages/en.json b/src/SharpEmu.GUI/Languages/en.json index fd5f8a1..57aa6dc 100644 --- a/src/SharpEmu.GUI/Languages/en.json +++ b/src/SharpEmu.GUI/Languages/en.json @@ -73,6 +73,11 @@ "Options.Section.Display": "DISPLAY", "Options.Graphics": "Graphics", + "Options.Console.Type.Label": "Console", + "Options.Console.Type.Desc": "Console model exposed to games.", + "Options.Console.Language.Label": "Console language", + "Options.Console.Language.Desc": "System language reported to games.", + "Options.WindowMode.Label": "Window mode", "Options.WindowMode.Desc": "Regular window, desktop borderless, or exclusive fullscreen.", "Options.WindowMode.Windowed": "Windowed", diff --git a/src/SharpEmu.GUI/Languages/es.json b/src/SharpEmu.GUI/Languages/es.json index 0fbef3e..ed9c052 100644 --- a/src/SharpEmu.GUI/Languages/es.json +++ b/src/SharpEmu.GUI/Languages/es.json @@ -206,6 +206,11 @@ "Updater.Status.ChecksumFailed": "La actualización descargada no superó la verificación SHA-256.", "Updater.Status.Unsupported": "La actualización automática requiere un build x64 de Windows, Linux o macOS.", "Options.Graphics": "Gráficos", + + "Options.Console.Type.Label": "Consola", + "Options.Console.Type.Desc": "Modelo de consola que se comunica a los juegos.", + "Options.Console.Language.Label": "Idioma de la consola", + "Options.Console.Language.Desc": "Idioma del sistema que se comunica a los juegos.", "Options.Section.Rendering": "RENDERIZADO", "Options.Section.Display": "PANTALLA", "Options.WindowMode.Label": "Modo de ventana", diff --git a/src/SharpEmu.GUI/Languages/fr.json b/src/SharpEmu.GUI/Languages/fr.json index 2c4d670..6ec4a2e 100644 --- a/src/SharpEmu.GUI/Languages/fr.json +++ b/src/SharpEmu.GUI/Languages/fr.json @@ -206,6 +206,11 @@ "Updater.Status.ChecksumFailed": "La mise à jour téléchargée a échoué à la vérification SHA-256.", "Updater.Status.Unsupported": "La mise à jour automatique nécessite un build x64 pour Windows, Linux ou macOS.", "Options.Graphics": "Graphismes", + + "Options.Console.Type.Label": "Console", + "Options.Console.Type.Desc": "Modèle de console signalé aux jeux.", + "Options.Console.Language.Label": "Langue de la console", + "Options.Console.Language.Desc": "Langue système signalée aux jeux.", "Options.Section.Rendering": "RENDU", "Options.Section.Display": "AFFICHAGE", "Options.WindowMode.Label": "Mode fenêtre", diff --git a/src/SharpEmu.GUI/Languages/hu.json b/src/SharpEmu.GUI/Languages/hu.json index 75606ac..c502b28 100644 --- a/src/SharpEmu.GUI/Languages/hu.json +++ b/src/SharpEmu.GUI/Languages/hu.json @@ -206,6 +206,11 @@ "Updater.Status.ChecksumFailed": "A letöltött frissítés nem ment át az SHA-256-ellenőrzésen.", "Updater.Status.Unsupported": "Az automatikus frissítéshez Windows, Linux vagy macOS x64 build szükséges.", "Options.Graphics": "Grafika", + + "Options.Console.Type.Label": "Konzol", + "Options.Console.Type.Desc": "A játékoknak jelentett konzolmodell.", + "Options.Console.Language.Label": "Konzol nyelve", + "Options.Console.Language.Desc": "A játékoknak jelentett rendszer nyelve.", "Options.Section.Rendering": "RENDERELÉS", "Options.Section.Display": "KIJELZŐ", "Options.WindowMode.Label": "Ablakmód", diff --git a/src/SharpEmu.GUI/Languages/it.json b/src/SharpEmu.GUI/Languages/it.json index d3eab27..551a3de 100644 --- a/src/SharpEmu.GUI/Languages/it.json +++ b/src/SharpEmu.GUI/Languages/it.json @@ -210,6 +210,11 @@ "Updater.Status.ChecksumFailed": "L'aggiornamento scaricato non ha superato la verifica SHA-256.", "Updater.Status.Unsupported": "L'aggiornamento automatico richiede un build x64 per Windows, Linux o macOS.", "Options.Graphics": "Grafica", + + "Options.Console.Type.Label": "Console", + "Options.Console.Type.Desc": "Modello di console comunicato ai giochi.", + "Options.Console.Language.Label": "Lingua della console", + "Options.Console.Language.Desc": "Lingua di sistema comunicata ai giochi.", "Options.Section.Rendering": "RENDERING", "Options.Section.Display": "SCHERMO", "Options.WindowMode.Label": "Modalità finestra", diff --git a/src/SharpEmu.GUI/Languages/ja.json b/src/SharpEmu.GUI/Languages/ja.json index c5ddccc..d1abed8 100644 --- a/src/SharpEmu.GUI/Languages/ja.json +++ b/src/SharpEmu.GUI/Languages/ja.json @@ -205,6 +205,11 @@ "Updater.Status.ChecksumFailed": "ダウンロードしたアップデートはSHA-256検証に失敗しました。", "Updater.Status.Unsupported": "自動アップデートにはWindows、Linux、またはmacOSのx64ビルドが必要です。", "Options.Graphics": "グラフィックス", + + "Options.Console.Type.Label": "コンソール", + "Options.Console.Type.Desc": "ゲームに通知するコンソールモデル。", + "Options.Console.Language.Label": "コンソールの言語", + "Options.Console.Language.Desc": "ゲームに通知するシステム言語。", "Options.Section.Rendering": "レンダリング", "Options.Section.Display": "ディスプレイ", "Options.WindowMode.Label": "ウィンドウモード", diff --git a/src/SharpEmu.GUI/Languages/ko.json b/src/SharpEmu.GUI/Languages/ko.json index cae6590..bde79fd 100644 --- a/src/SharpEmu.GUI/Languages/ko.json +++ b/src/SharpEmu.GUI/Languages/ko.json @@ -205,6 +205,11 @@ "Updater.Status.ChecksumFailed": "다운로드한 업데이트가 SHA-256 검증에 실패했습니다.", "Updater.Status.Unsupported": "자동 업데이트에는 Windows, Linux 또는 macOS x64 빌드가 필요합니다.", "Options.Graphics": "그래픽", + + "Options.Console.Type.Label": "콘솔", + "Options.Console.Type.Desc": "게임에 보고할 콘솔 모델입니다.", + "Options.Console.Language.Label": "콘솔 언어", + "Options.Console.Language.Desc": "게임에 보고할 시스템 언어입니다.", "Options.Section.Rendering": "렌더링", "Options.Section.Display": "디스플레이", "Options.WindowMode.Label": "창 모드", diff --git a/src/SharpEmu.GUI/Languages/nl.json b/src/SharpEmu.GUI/Languages/nl.json index 7425baa..e2a607e 100644 --- a/src/SharpEmu.GUI/Languages/nl.json +++ b/src/SharpEmu.GUI/Languages/nl.json @@ -205,6 +205,11 @@ "Updater.Status.ChecksumFailed": "De gedownloade update is niet door de SHA-256-verificatie gekomen.", "Updater.Status.Unsupported": "Automatisch updaten vereist een x64-build voor Windows, Linux of macOS.", "Options.Graphics": "Grafisch", + + "Options.Console.Type.Label": "Console", + "Options.Console.Type.Desc": "Consolemodel dat aan games wordt gemeld.", + "Options.Console.Language.Label": "Consoletaal", + "Options.Console.Language.Desc": "Systeemtaal die aan games wordt gemeld.", "Options.Section.Rendering": "RENDERING", "Options.Section.Display": "BEELDSCHERM", "Options.WindowMode.Label": "Venstermodus", diff --git a/src/SharpEmu.GUI/Languages/pl.json b/src/SharpEmu.GUI/Languages/pl.json index 7366ee2..e1b7b40 100644 --- a/src/SharpEmu.GUI/Languages/pl.json +++ b/src/SharpEmu.GUI/Languages/pl.json @@ -73,6 +73,11 @@ "Options.Section.Display": "WYŚWIETLANIE", "Options.Graphics": "Grafika", + "Options.Console.Type.Label": "Konsola", + "Options.Console.Type.Desc": "Model konsoli zgłaszany grom.", + "Options.Console.Language.Label": "Język konsoli", + "Options.Console.Language.Desc": "Język systemu zgłaszany grom.", + "Options.WindowMode.Label": "Tryb okna", "Options.WindowMode.Desc": "Zwykłe okno, bezramkowe na pulpicie lub pełny ekran wyłączny.", "Options.WindowMode.Windowed": "W oknie", diff --git a/src/SharpEmu.GUI/Languages/pt.json b/src/SharpEmu.GUI/Languages/pt.json index f55aa1b..1c32822 100644 --- a/src/SharpEmu.GUI/Languages/pt.json +++ b/src/SharpEmu.GUI/Languages/pt.json @@ -206,6 +206,11 @@ "Updater.Status.ChecksumFailed": "A atualização transferida falhou a verificação SHA-256.", "Updater.Status.Unsupported": "A atualização automática requer um build x64 para Windows, Linux ou macOS.", "Options.Graphics": "Gráficos", + + "Options.Console.Type.Label": "Consola", + "Options.Console.Type.Desc": "Modelo de consola comunicado aos jogos.", + "Options.Console.Language.Label": "Idioma da consola", + "Options.Console.Language.Desc": "Idioma do sistema comunicado aos jogos.", "Options.Section.Rendering": "RENDERIZAÇÃO", "Options.Section.Display": "ECRÃ", "Options.WindowMode.Label": "Modo de janela", diff --git a/src/SharpEmu.GUI/Languages/ru.json b/src/SharpEmu.GUI/Languages/ru.json index 8326bef..fd11033 100644 --- a/src/SharpEmu.GUI/Languages/ru.json +++ b/src/SharpEmu.GUI/Languages/ru.json @@ -69,6 +69,11 @@ "Options.Section.Display": "ЭКРАН", "Options.Graphics": "Графика", + "Options.Console.Type.Label": "Консоль", + "Options.Console.Type.Desc": "Модель консоли, сообщаемая играм.", + "Options.Console.Language.Label": "Язык консоли", + "Options.Console.Language.Desc": "Системный язык, сообщаемый играм.", + "Options.WindowMode.Label": "Режим окна", "Options.WindowMode.Desc": "Обычное окно, безрамочный режим рабочего стола или эксклюзивный полноэкранный режим.", "Options.WindowMode.Windowed": "Оконный", diff --git a/src/SharpEmu.GUI/Languages/tr.json b/src/SharpEmu.GUI/Languages/tr.json index 421cbc6..7ab007c 100644 --- a/src/SharpEmu.GUI/Languages/tr.json +++ b/src/SharpEmu.GUI/Languages/tr.json @@ -54,6 +54,11 @@ "Options.Section.Display": "GÖRÜNTÜ", "Options.Graphics": "Grafik", + "Options.Console.Type.Label": "Konsol", + "Options.Console.Type.Desc": "Oyunlara bildirilen konsol modeli.", + "Options.Console.Language.Label": "Konsol dili", + "Options.Console.Language.Desc": "Oyunlara bildirilen sistem dili.", + "Options.WindowMode.Label": "Pencere modu", "Options.WindowMode.Desc": "Normal pencere, kenarlıksız masaüstü veya özel tam ekran.", "Options.Resolution.Label": "Çözünürlük", diff --git a/src/SharpEmu.GUI/MainWindow.axaml b/src/SharpEmu.GUI/MainWindow.axaml index da9a172..518bb78 100644 --- a/src/SharpEmu.GUI/MainWindow.axaml +++ b/src/SharpEmu.GUI/MainWindow.axaml @@ -1185,6 +1185,28 @@ SPDX-License-Identifier: GPL-2.0-or-later VerticalAlignment="Center" /> + + + + + + + + _settings.CheckForUpdatesOnStartup = AutoUpdateToggle.IsChecked == true; + ConsoleTypeBox.SelectionChanged += (_, _) => + _settings.ConsoleType = SelectedComboText(ConsoleTypeBox, "PS5"); + ConsoleLanguageBox.SelectionChanged += (_, _) => + _settings.ConsoleLanguage = SelectedComboText(ConsoleLanguageBox, "EnglishUS"); WindowModeBox.SelectionChanged += (_, _) => _settings.WindowMode = SelectedComboText(WindowModeBox, "Windowed"); DisplayBox.SelectionChanged += (_, _) => OnHostDisplayChanged(); ResolutionBox.SelectionChanged += (_, _) => OnHostResolutionChanged(); @@ -1200,6 +1244,8 @@ public partial class MainWindow : Window private void InitializeLocalizedChoiceBoxes() { CpuEngineBox.ItemsSource = _cpuEngineChoices; + ConsoleTypeBox.ItemsSource = _consoleTypeChoices; + ConsoleLanguageBox.ItemsSource = _consoleLanguageChoices; LogLevelBox.ItemsSource = _logLevelChoices; WindowModeBox.ItemsSource = _windowModeChoices; ScalingModeBox.ItemsSource = _scalingModeChoices; @@ -1212,6 +1258,8 @@ public partial class MainWindow : Window private void RefreshLocalizedChoices() { RefreshChoices(_cpuEngineChoices); + RefreshChoices(_consoleTypeChoices); + RefreshChoices(_consoleLanguageChoices); RefreshChoices(_logLevelChoices); RefreshChoices(_windowModeChoices); RefreshChoices(_scalingModeChoices); @@ -1232,6 +1280,10 @@ public partial class MainWindow : Window private void ApplySettingsToControls() { CpuEngineBox.SelectedIndex = 0; + ConsoleTypeBox.SelectedIndex = 0; + ConsoleLanguageBox.SelectedIndex = ChoiceIndex( + _settings.ConsoleLanguage, + _consoleLanguageChoices.Select(choice => choice.Value).ToArray()); LogLevelBox.SelectedIndex = _settings.LogLevel.ToLowerInvariant() switch { "trace" => 0, @@ -2545,6 +2597,8 @@ public partial class MainWindow : Window Path.GetFullPath(ebootPath), displayName, _runningGameTitleId, + _settings.ConsoleType, + _settings.ConsoleLanguage, effective, runtimeOptions); @@ -2711,6 +2765,8 @@ public partial class MainWindow : Window { "--cpu-engine=native", $"--log-level={launch.Settings.LogLevel}", + $"--console={launch.ConsoleType.ToLowerInvariant()}", + $"--console-language={launch.ConsoleLanguage}", }; if (launch.RuntimeOptions.StrictDynlibResolution) { diff --git a/src/SharpEmu.Libs/SystemService/SystemServiceExports.cs b/src/SharpEmu.Libs/SystemService/SystemServiceExports.cs index f7c8f29..ba4bb05 100644 --- a/src/SharpEmu.Libs/SystemService/SystemServiceExports.cs +++ b/src/SharpEmu.Libs/SystemService/SystemServiceExports.cs @@ -19,10 +19,12 @@ public static class SystemServiceExports private static string? _mainAppTitleId; private static int _noticeScreenSkipFlag; + private static int _systemLanguage = 1; - public static void ConfigureApplicationInfo(string? titleId) + public static void ConfigureApplicationInfo(string? titleId, int systemLanguage = 1) { _mainAppTitleId = string.IsNullOrWhiteSpace(titleId) ? null : titleId.Trim(); + Volatile.Write(ref _systemLanguage, systemLanguage); } [SysAbiExport( @@ -114,7 +116,8 @@ public static class SystemServiceExports var value = parameterId switch { - 1 or 2 or 3 or 1000 => 1, + 1 or 400 => Volatile.Read(ref _systemLanguage), + 2 or 3 or 1000 => 1, 4 => 180, _ => 0, }; @@ -240,6 +243,9 @@ public static class SystemServiceExports LibraryName = "libSceSystemService")] public static int SystemServiceReportAbnormalTermination(CpuContext ctx) => ctx.SetReturn(0); - internal static void ResetForTests() => + internal static void ResetForTests() + { Volatile.Write(ref _noticeScreenSkipFlag, 0); + Volatile.Write(ref _systemLanguage, 1); + } } diff --git a/tests/SharpEmu.Libs.Tests/GUI/GuiSettingsTests.cs b/tests/SharpEmu.Libs.Tests/GUI/GuiSettingsTests.cs index 5f3ea01..90205e6 100644 --- a/tests/SharpEmu.Libs.Tests/GUI/GuiSettingsTests.cs +++ b/tests/SharpEmu.Libs.Tests/GUI/GuiSettingsTests.cs @@ -93,6 +93,8 @@ public sealed class GuiSettingsTests Assert.Equal("Info", settings.LogLevel); Assert.Equal("en", settings.Language); + Assert.Equal("PS5", settings.ConsoleType); + Assert.Equal("EnglishUS", settings.ConsoleLanguage); Assert.Equal("1525606762248540221", settings.DiscordClientId); Assert.Empty(settings.GameFolders); Assert.Empty(settings.ExcludedGames); @@ -128,6 +130,20 @@ public sealed class GuiSettingsTests Assert.Equal(1000, settings.RefreshRate); } + [Fact] + public void NormalizeFromJson_ConsoleValuesNormalizeAndPreserveValidLanguage() + { + var invalid = GuiSettings.NormalizeFromJson( + """{ "ConsoleType": "ps6", "ConsoleLanguage": "klingon" }"""); + var turkish = GuiSettings.NormalizeFromJson( + """{ "ConsoleType": "ps5", "ConsoleLanguage": "turkish" }"""); + + Assert.Equal("PS5", invalid.ConsoleType); + Assert.Equal("EnglishUS", invalid.ConsoleLanguage); + Assert.Equal("PS5", turkish.ConsoleType); + Assert.Equal("Turkish", turkish.ConsoleLanguage); + } + [Theory] [InlineData("""{ }""", "Carousel")] [InlineData("""{ "LibraryLayout": null }""", "Carousel")] diff --git a/tests/SharpEmu.Libs.Tests/SystemService/SystemServiceExportsTests.cs b/tests/SharpEmu.Libs.Tests/SystemService/SystemServiceExportsTests.cs index 9cb10d5..f95a657 100644 --- a/tests/SharpEmu.Libs.Tests/SystemService/SystemServiceExportsTests.cs +++ b/tests/SharpEmu.Libs.Tests/SystemService/SystemServiceExportsTests.cs @@ -3,6 +3,7 @@ using SharpEmu.HLE; using SharpEmu.Libs.SystemService; +using System.Buffers.Binary; using Xunit; namespace SharpEmu.Libs.Tests.SystemService; @@ -50,4 +51,24 @@ public sealed class SystemServiceExportsTests Assert.True(memory.TryRead(MemoryBase, flag)); Assert.Equal(1, flag[0]); } + + [Theory] + [InlineData(1)] + [InlineData(400)] + public void ParamGetIntReturnsConfiguredSystemLanguage(int parameterId) + { + var memory = new FakeCpuMemory(MemoryBase, sizeof(int)); + var context = new CpuContext(memory, Generation.Gen5) + { + [CpuRegister.Rdi] = unchecked((ulong)parameterId), + [CpuRegister.Rsi] = MemoryBase, + }; + SystemServiceExports.ConfigureApplicationInfo(null, 19); + + Assert.Equal(0, SystemServiceExports.SystemServiceParamGetInt(context)); + + Span value = stackalloc byte[sizeof(int)]; + Assert.True(memory.TryRead(MemoryBase, value)); + Assert.Equal(19, BinaryPrimitives.ReadInt32LittleEndian(value)); + } }