Compare commits

...
Author SHA1 Message Date
nmzik 05d14f5421 system: add console language conf 2026-08-03 01:37:42 +02:00
Stefanos Costaandnmzik 1a164c3628 kernel: preserve guest pthread priorities
Extracted from Stefanos Costa's pthread fix in #147.
2026-08-03 01:10:38 +02:00
9 changed files with 144 additions and 93 deletions
+4
View File
@@ -37,6 +37,10 @@ uint32_t GetVblankFrequency() {
return std::clamp(g_config->vblank_frequency, 30u, 360u);
}
uint32_t GetConsoleLanguage() {
return g_config->console_language;
}
bool VulkanValidationEnabled() {
return g_config->vulkan_validation_enabled;
}
+5
View File
@@ -18,10 +18,14 @@ enum class ProfilerDirection { None, Network };
enum class OutputDirection { Silent, Console, File };
constexpr uint32_t DEFAULT_CONSOLE_LANGUAGE = 1;
constexpr uint32_t MAX_CONSOLE_LANGUAGE = 29;
struct ConfigOptions {
uint32_t screen_width = 1280;
uint32_t screen_height = 720;
uint32_t vblank_frequency = 60;
uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE;
bool vulkan_validation_enabled = false;
bool shader_validation_enabled = false;
ShaderOptimizationType shader_optimization_type = ShaderOptimizationType::None;
@@ -43,6 +47,7 @@ void Load(const ConfigOptions& cfg);
uint32_t GetScreenWidth();
uint32_t GetScreenHeight();
uint32_t GetVblankFrequency();
uint32_t GetConsoleLanguage();
bool VulkanValidationEnabled();
bool ShaderValidationEnabled();
+30 -41
View File
@@ -365,6 +365,7 @@ struct PthreadAttrPrivate {
uint64_t stack_map_addr;
size_t stack_map_size;
int policy;
int guest_priority;
int inherit_sched;
int solosched;
bool detached;
@@ -2128,13 +2129,8 @@ int KYTY_SYSV_ABI PthreadAttrGetschedparam(const PthreadAttr* attr, KernelSchedP
int result = pthread_attr_getschedparam(&(*attr)->p, param);
if (param->sched_priority <= -2) {
param->sched_priority = 767;
} else if (param->sched_priority >= +2) {
param->sched_priority = 256;
} else {
param->sched_priority = 700;
}
// Host priority mapping is lossy; return the exact guest value.
param->sched_priority = (*attr)->guest_priority;
if (result == 0) {
return OK;
@@ -2298,6 +2294,7 @@ int KYTY_SYSV_ABI PthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedP
return KERNEL_ERROR_EINVAL;
}
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
KernelSchedParam pparam {};
if (param->sched_priority <= 478) {
pparam.sched_priority = +2;
@@ -2307,12 +2304,13 @@ int KYTY_SYSV_ABI PthreadAttrSetschedparam(PthreadAttr* attr, const KernelSchedP
pparam.sched_priority = 0;
}
int result = pthread_attr_setschedparam(&attr_value->p, &pparam);
if (result == 0) {
return OK;
}
if (pthread_attr_setschedparam(&attr_value->p, &pparam) != 0) {
return KERNEL_ERROR_EINVAL;
}
#endif
attr_value->guest_priority = param->sched_priority;
return OK;
}
int KYTY_SYSV_ABI PthreadAttrSetschedpolicy(PthreadAttr* attr, int policy) {
@@ -3639,26 +3637,15 @@ int KYTY_SYSV_ABI PthreadGetprio(Pthread thread, int* prio) {
EXIT_NOT_IMPLEMENTED(prio == nullptr);
sched_param param {};
int pol = 0;
int result = pthread_getschedparam(thread->p, &pol, &param);
if (result == 0) {
if (param.sched_priority <= -2) {
*prio = 767;
} else if (param.sched_priority >= +2) {
*prio = 256;
} else {
*prio = 700;
}
LOGF("\t PthreadGetprio: %d, %d\n", thread->unique_id, *prio);
return OK;
}
sched_param native_param {};
int native_policy = 0;
if (pthread_getschedparam(thread->p, &native_policy, &native_param) != 0) {
return KERNEL_ERROR_EINVAL;
}
*prio = thread->attr->guest_priority;
LOGF("\t PthreadGetprio: %d, %d\n", thread->unique_id, *prio);
return OK;
}
int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio) {
@@ -3673,7 +3660,11 @@ int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio) {
int result = pthread_getschedparam(thread->p, &pol, &param);
if (result == 0) {
if (result != 0) {
return KERNEL_ERROR_EINVAL;
}
#if KYTY_PLATFORM == KYTY_PLATFORM_WINDOWS
if (prio <= 478) {
param.sched_priority = +2;
} else if (prio >= 733) {
@@ -3682,16 +3673,14 @@ int KYTY_SYSV_ABI PthreadSetprio(Pthread thread, int prio) {
param.sched_priority = 0;
}
result = pthread_setschedparam(thread->p, pol, &param);
if (result == 0) {
LOGF("\t PthreadSetprio: %d, %d\n", thread->unique_id, prio);
return OK;
}
}
if (pthread_setschedparam(thread->p, pol, &param) != 0) {
return KERNEL_ERROR_EINVAL;
}
#endif
thread->attr->guest_priority = prio;
LOGF("\t PthreadSetprio: %d, %d\n", thread->unique_id, prio);
return OK;
}
void KYTY_SYSV_ABI PthreadTestcancel() {
+28 -14
View File
@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>560</width>
<height>420</height>
<height>450</height>
</rect>
</property>
<property name="windowTitle">
@@ -119,41 +119,55 @@
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="label_console_language">
<property name="text">
<string>Console language:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<widget class="QComboBox" name="comboBox_console_language">
<property name="toolTip">
<string>Language</string>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="label_20">
<property name="text">
<string>Shader optimization type:</string>
</property>
</widget>
</item>
<item row="3" column="1">
<item row="4" column="1">
<widget class="QComboBox" name="comboBox_shader_optimization_type">
<property name="toolTip">
<string>Optimize shaders for code size or performance</string>
</property>
</widget>
</item>
<item row="4" column="0">
<item row="5" column="0">
<widget class="QLabel" name="label_21">
<property name="text">
<string>Shader log direction:</string>
</property>
</widget>
</item>
<item row="4" column="1">
<item row="5" column="1">
<widget class="QComboBox" name="comboBox_shader_log_direction">
<property name="toolTip">
<string>Dump shaders to file or console window. If enabled may decrease emulator performance</string>
</property>
</widget>
</item>
<item row="5" column="0">
<item row="6" column="0">
<widget class="QLabel" name="label_22">
<property name="text">
<string>Shader log folder:</string>
</property>
</widget>
</item>
<item row="5" column="1">
<item row="6" column="1">
<widget class="MandatoryLineEdit" name="lineEdit_shader_log_folder">
<property name="toolTip">
<string>Specify directory to dump shaders</string>
@@ -163,14 +177,14 @@
</property>
</widget>
</item>
<item row="6" column="0">
<item row="7" column="0">
<widget class="QLabel" name="label_24">
<property name="text">
<string>Command buffer dump folder:</string>
</property>
</widget>
</item>
<item row="6" column="1">
<item row="7" column="1">
<widget class="MandatoryLineEdit" name="lineEdit_cmd_dump_folder">
<property name="toolTip">
<string>Specify directory to dump command buffers</string>
@@ -180,28 +194,28 @@
</property>
</widget>
</item>
<item row="7" column="0">
<item row="8" column="0">
<widget class="QLabel" name="label_25">
<property name="text">
<string>Printf direction:</string>
</property>
</widget>
</item>
<item row="7" column="1">
<item row="8" column="1">
<widget class="QComboBox" name="comboBox_printf_direction">
<property name="toolTip">
<string>Print logs to file or console window. If enabled may decrease emulator performance</string>
</property>
</widget>
</item>
<item row="8" column="0">
<item row="9" column="0">
<widget class="QLabel" name="label_26">
<property name="text">
<string>Printf output file:</string>
</property>
</widget>
</item>
<item row="8" column="1">
<item row="9" column="1">
<widget class="MandatoryLineEdit" name="lineEdit_printf_file">
<property name="toolTip">
<string>Specify file to dump logs</string>
@@ -211,14 +225,14 @@
</property>
</widget>
</item>
<item row="9" column="0">
<item row="10" column="0">
<widget class="QLabel" name="label_27">
<property name="text">
<string>Profiler direction:</string>
</property>
</widget>
</item>
<item row="9" column="1">
<item row="10" column="1">
<widget class="QComboBox" name="comboBox_profiler_direction">
<property name="toolTip">
<string>Enable or disable profiler. If enabled may decrease emulator performance</string>
+10
View File
@@ -48,6 +48,9 @@ class Configuration: public QObject {
Q_OBJECT
public:
static constexpr int DEFAULT_CONSOLE_LANGUAGE = 1;
static constexpr int MAX_CONSOLE_LANGUAGE = 29;
enum class Resolution {
R1280X720,
R1920X1080,
@@ -83,6 +86,7 @@ public:
Resolution screen_resolution = Resolution::R1280X720;
int vblank_frequency = 60;
int console_language = DEFAULT_CONSOLE_LANGUAGE;
bool vulkan_validation_enabled = true;
bool shader_validation_enabled = true;
ShaderOptimizationType shader_optimization_type = ShaderOptimizationType::Performance;
@@ -100,6 +104,7 @@ public:
void CopyEmulatorSettingsFrom(const Configuration& other) {
screen_resolution = other.screen_resolution;
vblank_frequency = other.vblank_frequency;
console_language = other.console_language;
vulkan_validation_enabled = other.vulkan_validation_enabled;
shader_validation_enabled = other.shader_validation_enabled;
shader_optimization_type = other.shader_optimization_type;
@@ -134,6 +139,7 @@ public:
KYTY_CFG_SET(custom_settings);
KYTY_CFG_SET(screen_resolution);
KYTY_CFG_SET(vblank_frequency);
KYTY_CFG_SET(console_language);
KYTY_CFG_SET(vulkan_validation_enabled);
KYTY_CFG_SET(shader_validation_enabled);
KYTY_CFG_SET(shader_optimization_type);
@@ -155,6 +161,10 @@ public:
KYTY_CFG_GET(custom_settings);
KYTY_CFG_GET(screen_resolution);
vblank_frequency = s->value("vblank_frequency", vblank_frequency).toInt();
console_language = s->value("console_language", console_language).toInt();
if (console_language < 0 || console_language > MAX_CONSOLE_LANGUAGE) {
console_language = DEFAULT_CONSOLE_LANGUAGE;
}
KYTY_CFG_GET(vulkan_validation_enabled);
KYTY_CFG_GET(shader_validation_enabled);
KYTY_CFG_GET(shader_optimization_type);
@@ -30,6 +30,39 @@ constexpr char SETTINGS_CFG_DIALOG[] = "ConfigurationEditDialog";
constexpr char SETTINGS_CFG_LAST_GEOMETRY[] = "geometry";
constexpr int GLOBAL_SETTINGS_GAME_DIRS_MIN_WIDTH = 560;
const QStringList CONSOLE_LANGUAGE_NAMES = {
"Japanese",
"English (United States)",
"French (France)",
"Spanish (Spain)",
"German",
"Italian",
"Dutch",
"Portuguese (Portugal)",
"Russian",
"Korean",
"Chinese (Traditional)",
"Chinese (Simplified)",
"Finnish",
"Swedish",
"Danish",
"Norwegian",
"Polish",
"Portuguese (Brazil)",
"English (United Kingdom)",
"Turkish",
"Spanish (Latin America)",
"Arabic",
"French (Canada)",
"Czech",
"Hungarian",
"Greek",
"Romanian",
"Thai",
"Vietnamese",
"Indonesian",
};
static QString NormalizeGameDirectory(const QString& dir) {
const auto trimmed = dir.trimmed();
if (trimmed.isEmpty()) {
@@ -121,6 +154,12 @@ static void ListInit(QComboBox* combo, T value) {
void ConfigurationEditDialog::Init(const Configuration& info) {
ListInit(m_ui->comboBox_screen_resolution, info.screen_resolution);
m_ui->spinBox_vblank_frequency->setValue(info.vblank_frequency);
m_ui->comboBox_console_language->clear();
m_ui->comboBox_console_language->addItems(CONSOLE_LANGUAGE_NAMES);
m_ui->comboBox_console_language->setCurrentIndex(
info.console_language >= 0 && info.console_language < CONSOLE_LANGUAGE_NAMES.size()
? info.console_language
: Configuration::DEFAULT_CONSOLE_LANGUAGE);
m_ui->checkBox_shader_validation->setChecked(info.shader_validation_enabled);
m_ui->checkBox_vulkan_validation->setChecked(info.vulkan_validation_enabled);
m_ui->checkBox_renderdoc_capture->setChecked(info.renderdoc_enabled);
@@ -241,6 +280,7 @@ static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) {
info.screen_resolution =
TextToEnum<Configuration::Resolution>(ui.comboBox_screen_resolution->currentText());
info.vblank_frequency = ui.spinBox_vblank_frequency->value();
info.console_language = ui.comboBox_console_language->currentIndex();
info.vulkan_validation_enabled = ui.checkBox_vulkan_validation->isChecked();
info.shader_validation_enabled = ui.checkBox_shader_validation->isChecked();
info.renderdoc_enabled = ui.checkBox_renderdoc_capture->isChecked();
+1
View File
@@ -205,6 +205,7 @@ static QStringList CreateEmulatorArgs(const Configuration& info) {
args << "--screen-width" << r.at(0);
args << "--screen-height" << r.at(1);
args << "--vblank-frequency" << QString::number(info.vblank_frequency);
args << "--console-language" << QString::number(info.console_language);
args << "--vulkan-validation" << BoolArg(info.vulkan_validation_enabled);
args << "--shader-validation" << BoolArg(info.shader_validation_enabled);
args << "--shader-optimization-type" << EnumToText(info.shader_optimization_type);
+2 -32
View File
@@ -1,6 +1,7 @@
#include "common/abi.h"
#include "common/assert.h"
#include "common/common.h"
#include "common/emulatorConfig.h"
#include "common/logging/log.h"
#include "common/stringUtils.h"
#include "libs/errno.h"
@@ -25,37 +26,6 @@ namespace SystemService {
[[maybe_unused]] constexpr int PARAM_ID_SCREEN_READER = 208;
[[maybe_unused]] constexpr int PARAM_ID_ENTER_BUTTON_ASSIGN = 1000;
[[maybe_unused]] constexpr int PARAM_LANG_JAPANESE = 0;
[[maybe_unused]] constexpr int PARAM_LANG_ENGLISH_US = 1;
[[maybe_unused]] constexpr int PARAM_LANG_FRENCH = 2;
[[maybe_unused]] constexpr int PARAM_LANG_SPANISH = 3;
[[maybe_unused]] constexpr int PARAM_LANG_GERMAN = 4;
[[maybe_unused]] constexpr int PARAM_LANG_ITALIAN = 5;
[[maybe_unused]] constexpr int PARAM_LANG_DUTCH = 6;
[[maybe_unused]] constexpr int PARAM_LANG_PORTUGUESE_PT = 7;
[[maybe_unused]] constexpr int PARAM_LANG_RUSSIAN = 8;
[[maybe_unused]] constexpr int PARAM_LANG_KOREAN = 9;
[[maybe_unused]] constexpr int PARAM_LANG_CHINESE_T = 10;
[[maybe_unused]] constexpr int PARAM_LANG_CHINESE_S = 11;
[[maybe_unused]] constexpr int PARAM_LANG_FINNISH = 12;
[[maybe_unused]] constexpr int PARAM_LANG_SWEDISH = 13;
[[maybe_unused]] constexpr int PARAM_LANG_DANISH = 14;
[[maybe_unused]] constexpr int PARAM_LANG_NORWEGIAN = 15;
[[maybe_unused]] constexpr int PARAM_LANG_POLISH = 16;
[[maybe_unused]] constexpr int PARAM_LANG_PORTUGUESE_BR = 17;
[[maybe_unused]] constexpr int PARAM_LANG_ENGLISH_GB = 18;
[[maybe_unused]] constexpr int PARAM_LANG_TURKISH = 19;
[[maybe_unused]] constexpr int PARAM_LANG_SPANISH_LA = 20;
[[maybe_unused]] constexpr int PARAM_LANG_ARABIC = 21;
[[maybe_unused]] constexpr int PARAM_LANG_FRENCH_CA = 22;
[[maybe_unused]] constexpr int PARAM_LANG_CZECH = 23;
[[maybe_unused]] constexpr int PARAM_LANG_HUNGARIAN = 24;
[[maybe_unused]] constexpr int PARAM_LANG_GREEK = 25;
[[maybe_unused]] constexpr int PARAM_LANG_ROMANIAN = 26;
[[maybe_unused]] constexpr int PARAM_LANG_THAI = 27;
[[maybe_unused]] constexpr int PARAM_LANG_VIETNAMESE = 28;
[[maybe_unused]] constexpr int PARAM_LANG_INDONESIAN = 29;
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_YYYYMMDD = 0;
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_DDMMYYYY = 1;
[[maybe_unused]] constexpr int PARAM_DATE_FORMAT_MMDDYYYY = 2;
@@ -121,7 +91,7 @@ static int KYTY_SYSV_ABI SystemServiceParamGetInt(int param_id, int* value) {
int v = 0;
switch (param_id) {
case PARAM_ID_LANG: v = PARAM_LANG_ENGLISH_US; break;
case PARAM_ID_LANG: v = static_cast<int>(Config::GetConsoleLanguage()); break;
case PARAM_ID_DATE_FORMAT: v = PARAM_DATE_FORMAT_DDMMYYYY; break;
case PARAM_ID_TIME_FORMAT: v = PARAM_TIME_FORMAT_24HOUR; break;
case PARAM_ID_TIME_ZONE: v = +180; break;
+18
View File
@@ -10,6 +10,7 @@
#include "emulator.h"
#include "kytyGitVersion.h"
#include <charconv>
#include <cstdio>
#include <fmt/format.h>
@@ -47,6 +48,7 @@ static void PrintUsage() {
::printf(" --screen-width <num> Window width. Default: 1280.\n");
::printf(" --screen-height <num> Window height. Default: 720.\n");
::printf(" --vblank-frequency <num> Virtual vblank frequency. Default: 60.\n");
::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n");
::printf(" --vulkan-validation <true|false> Enable Vulkan validation.\n");
::printf(" --shader-validation <true|false> Enable shader validation.\n");
::printf(" --shader-optimization-type <value> None, Size, or Performance.\n");
@@ -101,6 +103,17 @@ static bool ParseEnum(const std::string& value, E& out) {
return true;
}
static bool ParseConsoleLanguage(const std::string& value, uint32_t& out) {
uint32_t language = 0;
auto [end, error] = std::from_chars(value.data(), value.data() + value.size(), language);
if (error != std::errc {} || end != value.data() + value.size() ||
language > Config::MAX_CONSOLE_LANGUAGE) {
return false;
}
out = language;
return true;
}
static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_help) {
show_help = false;
@@ -167,6 +180,11 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he
const int32_t vblank_frequency = Common::ToInt32(value);
options.config.vblank_frequency =
static_cast<uint32_t>(vblank_frequency < 0 ? 0 : vblank_frequency);
} else if (arg == "--console-language") {
if (!ParseConsoleLanguage(value, options.config.console_language)) {
::printf("invalid console language: %s\n", value.c_str());
return false;
}
} else if (arg == "--vulkan-validation") {
if (!ParseBool(value, options.config.vulkan_validation_enabled)) {
::printf("invalid boolean for %s: %s\n", arg.c_str(), value.c_str());