early-access version 4120

This commit is contained in:
pineappleEA 2024-02-07 23:41:59 +01:00
parent 4e075a8090
commit ae234410db
7 changed files with 59 additions and 103 deletions

View File

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 4119. This is the source code for early-access 4120.
## Legal Notice ## Legal Notice

View File

@ -3,8 +3,8 @@
import android.annotation.SuppressLint import android.annotation.SuppressLint
import kotlin.collections.setOf import kotlin.collections.setOf
import org.jetbrains.kotlin.konan.properties.Properties
import org.jlleitschuh.gradle.ktlint.reporter.ReporterType import org.jlleitschuh.gradle.ktlint.reporter.ReporterType
import com.github.triplet.gradle.androidpublisher.ReleaseStatus
plugins { plugins {
id("com.android.application") id("com.android.application")
@ -13,6 +13,7 @@ plugins {
kotlin("plugin.serialization") version "1.9.20" kotlin("plugin.serialization") version "1.9.20"
id("androidx.navigation.safeargs.kotlin") id("androidx.navigation.safeargs.kotlin")
id("org.jlleitschuh.gradle.ktlint") version "11.4.0" id("org.jlleitschuh.gradle.ktlint") version "11.4.0"
id("com.github.triplet.play") version "3.8.6"
} }
/** /**
@ -58,15 +59,7 @@ android {
targetSdk = 34 targetSdk = 34
versionName = getGitVersion() versionName = getGitVersion()
// If you want to use autoVersion for the versionCode, create a property in local.properties versionCode = if (System.getenv("AUTO_VERSIONED") == "true") {
// named "autoVersioned" and set it to "true"
val properties = Properties()
val versionProperty = try {
properties.load(project.rootProject.file("local.properties").inputStream())
properties.getProperty("autoVersioned") ?: ""
} catch (e: Exception) { "" }
versionCode = if (versionProperty == "true") {
autoVersion autoVersion
} else { } else {
1 1
@ -221,6 +214,15 @@ ktlint {
} }
} }
play {
val keyPath = System.getenv("SERVICE_ACCOUNT_KEY_PATH")
if (keyPath != null) {
serviceAccountCredentials.set(File(keyPath))
}
track.set(System.getenv("STORE_TRACK") ?: "internal")
releaseStatus.set(ReleaseStatus.COMPLETED)
}
dependencies { dependencies {
implementation("androidx.core:core-ktx:1.12.0") implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.appcompat:appcompat:1.6.1") implementation("androidx.appcompat:appcompat:1.6.1")
@ -257,14 +259,13 @@ fun runGitCommand(command: List<String>): String {
} }
fun getGitVersion(): String { fun getGitVersion(): String {
val gitVersion = runGitCommand(listOf("git", "describe", "--always", "--long"))
val versionName = if (System.getenv("GITHUB_ACTIONS") != null) { val versionName = if (System.getenv("GITHUB_ACTIONS") != null) {
val gitTag = System.getenv("GIT_TAG_NAME") ?: "" System.getenv("GIT_TAG_NAME") ?: gitVersion
gitTag
} else { } else {
runGitCommand(listOf("git", "describe", "--always", "--long")) gitVersion
.replace(Regex("(-0)?-[^-]+$"), "")
} }
return versionName.ifEmpty { "0.0" } return versionName.replace(Regex("(-0)?-[^-]+$"), "").ifEmpty { "0.0" }
} }
fun getGitHash(): String = fun getGitHash(): String =

View File

@ -280,7 +280,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE
u32 value{}; u32 value{};
std::memcpy(&value, raw_data + ArgOffset, ArgSize); std::memcpy(&value, raw_data + ArgOffset, ArgSize);
std::get<ArgIndex>(args) = ctx.GetDomainHandler<ArgType::Type>(value - 1); std::get<ArgIndex>(args) = ctx.GetDomainHandler<typename ArgType::element_type>(value - 1);
return ReadInArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp); return ReadInArgument<MethodArguments, CallArguments, ArgAlign, ArgEnd, HandleIndex, InBufferIndex, OutBufferIndex, true, ArgIndex + 1>(is_domain, args, raw_data, ctx, temp);
} else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) { } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) {

View File

@ -65,6 +65,14 @@ struct ClientProcessId {
}; };
struct ProcessId { struct ProcessId {
explicit ProcessId() : pid() {}
explicit ProcessId(u64 p) : pid(p) {}
/* implicit */ ProcessId(const ClientProcessId& c) : pid(c.pid) {}
bool operator==(const ProcessId& rhs) const {
return pid == rhs.pid;
}
explicit operator bool() const { explicit operator bool() const {
return pid != 0; return pid != 0;
} }
@ -291,4 +299,4 @@ private:
}; };
// clang-format on // clang-format on
} // namespace Service } // namespace Service

View File

@ -299,8 +299,12 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer() {
if (GetManager()->IsDomain()) { if (GetManager()->IsDomain()) {
current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size());
for (auto& object : outgoing_domain_objects) { for (auto& object : outgoing_domain_objects) {
GetManager()->AppendDomainHandler(std::move(object)); if (object) {
cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount()); GetManager()->AppendDomainHandler(std::move(object));
cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount());
} else {
cmd_buf[current_offset++] = 0;
}
} }
} }

View File

@ -32,9 +32,14 @@ struct Client::Impl {
Impl(std::string host_, std::string username_, std::string token_) Impl(std::string host_, std::string username_, std::string token_)
: host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} { : host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} {
std::scoped_lock lock{jwt_cache.mutex}; std::scoped_lock lock{jwt_cache.mutex};
if (username == jwt_cache.username && token == jwt_cache.token) { if (this->username == jwt_cache.username && this->token == jwt_cache.token) {
jwt = jwt_cache.jwt; jwt = jwt_cache.jwt;
} }
// Normalize host expression
if (!this->host.empty() && this->host.back() == '/') {
static_cast<void>(this->host.pop_back());
}
} }
/// A generic function handles POST, GET and DELETE request together /// A generic function handles POST, GET and DELETE request together
@ -71,18 +76,16 @@ struct Client::Impl {
const std::string& jwt_ = "", const std::string& username_ = "", const std::string& jwt_ = "", const std::string& username_ = "",
const std::string& token_ = "") { const std::string& token_ = "") {
if (cli == nullptr) { if (cli == nullptr) {
cli = std::make_unique<httplib::Client>(host); cli = std::make_unique<httplib::Client>(host.c_str());
cli->set_connection_timeout(TIMEOUT_SECONDS);
cli->set_read_timeout(TIMEOUT_SECONDS);
cli->set_write_timeout(TIMEOUT_SECONDS);
} }
if (!cli->is_valid()) { if (!cli->is_valid()) {
LOG_ERROR(WebService, "Client is invalid, skipping request!"); LOG_ERROR(WebService, "Invalid URL {}", host + path);
return {}; return WebResult{WebResult::Code::InvalidURL, "Invalid URL", ""};
} }
cli->set_connection_timeout(TIMEOUT_SECONDS);
cli->set_read_timeout(TIMEOUT_SECONDS);
cli->set_write_timeout(TIMEOUT_SECONDS);
httplib::Headers params; httplib::Headers params;
if (!jwt_.empty()) { if (!jwt_.empty()) {
params = { params = {
@ -107,15 +110,15 @@ struct Client::Impl {
request.headers = params; request.headers = params;
request.body = data; request.body = data;
httplib::Response response; httplib::Result result = cli->send(request);
httplib::Error error;
if (!cli->send(request, response, error)) { if (!result) {
LOG_ERROR(WebService, "{} to {} returned null (httplib Error: {})", method, host + path, LOG_ERROR(WebService, "{} to {} returned null", method, host + path);
httplib::to_string(error));
return WebResult{WebResult::Code::LibError, "Null response", ""}; return WebResult{WebResult::Code::LibError, "Null response", ""};
} }
httplib::Response response = result.value();
if (response.status >= 400) { if (response.status >= 400) {
LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path, LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path,
response.status); response.status);

View File

@ -248,82 +248,22 @@ void ConfigureUi::RetranslateUI() {
} }
void ConfigureUi::InitializeLanguageComboBox() { void ConfigureUi::InitializeLanguageComboBox() {
// This is a list of lexicographically sorted languages, only the available translations are
// shown to the user.
static const struct {
const QString name;
const char* id;
} languages[] = {
// clang-format off
{QStringLiteral(u"Bahasa Indonesia"), "id"}, // Indonesian
{QStringLiteral(u"Bahasa Melayu"), "ms"}, // Malay
{QStringLiteral(u"Catal\u00E0"), "ca"}, // Catalan
{QStringLiteral(u"\u010Ce\u0161tina"), "cs"}, // Czech
{QStringLiteral(u"Dansk"), "da"}, // Danish
{QStringLiteral(u"Deutsch"), "de"}, // German
{QStringLiteral(u"English"), "en"}, // English
{QStringLiteral(u"Espa\u00F1ol"), "es"}, // Spanish
{QStringLiteral(u"Fran\u00E7ais"), "fr"}, // French
{QStringLiteral(u"Hrvatski"), "hr"}, // Croatian
{QStringLiteral(u"Italiano"), "it"}, // Italian
{QStringLiteral(u"Magyar"), "hu"}, // Hungarian
{QStringLiteral(u"Nederlands"), "nl"}, // Dutch
{QStringLiteral(u"Norsk bokm\u00E5l"), "nb"}, // Norwegian
{QStringLiteral(u"Polski"), "pl"}, // Polish
{QStringLiteral(u"Portugu\u00EAs"), "pt_PT"}, // Portuguese
{QStringLiteral(u"Portugu\u00EAs (Brasil)"), "pt_BR"}, // Portuguese (Brazil)
{QStringLiteral(u"Rom\u00E2n\u0103"), "ro"}, // Romanian
{QStringLiteral(u"Srpski"), "sr"}, // Serbian
{QStringLiteral(u"Suomi"), "fi"}, // Finnish
{QStringLiteral(u"Svenska"), "sv"}, // Swedish
{QStringLiteral(u"Ti\u1EBFng Vi\u1EC7t"), "vi"}, // Vietnamese
{QStringLiteral(u"Ti\u1EBFng Vi\u1EC7t (Vi\u1EC7t Nam)"), "vi_VN"}, // Vietnamese
{QStringLiteral(u"T\u00FCrk\u00E7e"), "tr_TR"}, // Turkish
{QStringLiteral(u"\u0395\u03BB\u03BB\u03B7\u03BD\u03B9\u03BA\u03AC"), "el"}, // Greek
{QStringLiteral(u"\u0420\u0443\u0441\u0441\u043A\u0438\u0439"), "ru_RU"}, // Russian
{QStringLiteral(u"\u0423\u043A\u0440\u0430\u0457\u043D\u0441\u044C\u043A\u0430"),
"uk"}, // Ukrainian
{QStringLiteral(u"\u0627\u0644\u0639\u0631\u0628\u064A\u0629"), "ar"}, // Arabic
{QStringLiteral(u"\u0641\u0627\u0631\u0633\u06CC"), "fa"}, // Farsi
{QStringLiteral(u"\uD55C\uAD6D\uC5B4"), "ko_KR"}, // Korean
{QStringLiteral(u"\u65E5\u672C\u8A9E"), "ja_JP"}, // Japanese
{QStringLiteral(u"\u7B80\u4F53\u4E2D\u6587"), "zh_CN"}, // Simplified Chinese
{QStringLiteral(u"\u7E41\u9AD4\u4E2D\u6587"), "zh_TW"}, // Traditional Chinese
// clang-format on
};
ui->language_combobox->addItem(tr("<System>"), QString{}); ui->language_combobox->addItem(tr("<System>"), QString{});
QDir languages_dir{QStringLiteral(":/languages")}; ui->language_combobox->addItem(tr("English"), QStringLiteral("en"));
QStringList language_files = languages_dir.entryList(); QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags);
for (const auto& lang : languages) { while (it.hasNext()) {
if (QString::fromLatin1(lang.id) == QStringLiteral("en")) { QString locale = it.next();
ui->language_combobox->addItem(lang.name, QStringLiteral("en"));
language_files.removeOne(QStringLiteral("en.qm"));
continue;
}
for (int i = 0; i < language_files.size(); ++i) {
QString locale = language_files[i];
locale.truncate(locale.lastIndexOf(QLatin1Char{'.'}));
if (QString::fromLatin1(lang.id) == locale) {
ui->language_combobox->addItem(lang.name, locale);
language_files.removeAt(i);
break;
}
}
}
// Anything remaining will be at the bottom
for (const QString& file : language_files) {
LOG_CRITICAL(Frontend, "Unexpected Language File: {}", file.toStdString());
QString locale = file;
locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); locale.truncate(locale.lastIndexOf(QLatin1Char{'.'}));
const QString language_name = QLocale::languageToString(QLocale(locale).language()); locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1);
const QString lang = QStringLiteral("%1 [%2]").arg(language_name, locale); const QString lang = QLocale::languageToString(QLocale(locale).language());
ui->language_combobox->addItem(lang, locale); const QString country = QLocale::countryToString(QLocale(locale).country());
ui->language_combobox->addItem(QStringLiteral("%1 (%2)").arg(lang, country), locale);
} }
// Unlike other configuration changes, interface language changes need to be reflected on the // Unlike other configuration changes, interface language changes need to be reflected on the
// interface immediately. This is done by passing a signal to the main window, and then // interface immediately. This is done by passing a signal to the main window, and then
// retranslating when passing back. // retranslating when passing back.
connect(ui->language_combobox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, connect(ui->language_combobox, qOverload<int>(&QComboBox::currentIndexChanged), this,
&ConfigureUi::OnLanguageChanged); &ConfigureUi::OnLanguageChanged);
} }