early-access version 4120
This commit is contained in:
		| @@ -1,7 +1,7 @@ | ||||
| yuzu emulator early access | ||||
| ============= | ||||
|  | ||||
| This is the source code for early-access 4119. | ||||
| This is the source code for early-access 4120. | ||||
|  | ||||
| ## Legal Notice | ||||
|  | ||||
|   | ||||
| @@ -3,8 +3,8 @@ | ||||
|  | ||||
| import android.annotation.SuppressLint | ||||
| import kotlin.collections.setOf | ||||
| import org.jetbrains.kotlin.konan.properties.Properties | ||||
| import org.jlleitschuh.gradle.ktlint.reporter.ReporterType | ||||
| import com.github.triplet.gradle.androidpublisher.ReleaseStatus | ||||
|  | ||||
| plugins { | ||||
|     id("com.android.application") | ||||
| @@ -13,6 +13,7 @@ plugins { | ||||
|     kotlin("plugin.serialization") version "1.9.20" | ||||
|     id("androidx.navigation.safeargs.kotlin") | ||||
|     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 | ||||
|         versionName = getGitVersion() | ||||
|  | ||||
|         // If you want to use autoVersion for the versionCode, create a property in local.properties | ||||
|         // 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") { | ||||
|         versionCode = if (System.getenv("AUTO_VERSIONED") == "true") { | ||||
|             autoVersion | ||||
|         } else { | ||||
|             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 { | ||||
|     implementation("androidx.core:core-ktx:1.12.0") | ||||
|     implementation("androidx.appcompat:appcompat:1.6.1") | ||||
| @@ -257,14 +259,13 @@ fun runGitCommand(command: List<String>): String { | ||||
| } | ||||
|  | ||||
| fun getGitVersion(): String { | ||||
|     val gitVersion = runGitCommand(listOf("git", "describe", "--always", "--long")) | ||||
|     val versionName = if (System.getenv("GITHUB_ACTIONS") != null) { | ||||
|         val gitTag = System.getenv("GIT_TAG_NAME") ?: "" | ||||
|         gitTag | ||||
|         System.getenv("GIT_TAG_NAME") ?: gitVersion | ||||
|     } else { | ||||
|         runGitCommand(listOf("git", "describe", "--always", "--long")) | ||||
|             .replace(Regex("(-0)?-[^-]+$"), "") | ||||
|         gitVersion | ||||
|     } | ||||
|     return versionName.ifEmpty { "0.0" } | ||||
|     return versionName.replace(Regex("(-0)?-[^-]+$"), "").ifEmpty { "0.0" } | ||||
| } | ||||
|  | ||||
| fun getGitHash(): String = | ||||
|   | ||||
| @@ -280,7 +280,7 @@ void ReadInArgument(bool is_domain, CallArguments& args, const u8* raw_data, HLE | ||||
|  | ||||
|             u32 value{}; | ||||
|             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); | ||||
|         } else if constexpr (ArgumentTraits<ArgType>::Type == ArgumentType::InCopyHandle) { | ||||
|   | ||||
| @@ -65,6 +65,14 @@ struct ClientProcessId { | ||||
| }; | ||||
|  | ||||
| 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 { | ||||
|         return pid != 0; | ||||
|     } | ||||
| @@ -291,4 +299,4 @@ private: | ||||
| }; | ||||
| // clang-format on | ||||
|  | ||||
| } // namespace Service | ||||
| } // namespace Service | ||||
|   | ||||
| @@ -299,8 +299,12 @@ Result HLERequestContext::WriteToOutgoingCommandBuffer() { | ||||
|     if (GetManager()->IsDomain()) { | ||||
|         current_offset = domain_offset - static_cast<u32>(outgoing_domain_objects.size()); | ||||
|         for (auto& object : outgoing_domain_objects) { | ||||
|             GetManager()->AppendDomainHandler(std::move(object)); | ||||
|             cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount()); | ||||
|             if (object) { | ||||
|                 GetManager()->AppendDomainHandler(std::move(object)); | ||||
|                 cmd_buf[current_offset++] = static_cast<u32_le>(GetManager()->DomainHandlerCount()); | ||||
|             } else { | ||||
|                 cmd_buf[current_offset++] = 0; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -32,9 +32,14 @@ struct Client::Impl { | ||||
|     Impl(std::string host_, std::string username_, std::string token_) | ||||
|         : host{std::move(host_)}, username{std::move(username_)}, token{std::move(token_)} { | ||||
|         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; | ||||
|         } | ||||
|  | ||||
|         // 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 | ||||
| @@ -71,18 +76,16 @@ struct Client::Impl { | ||||
|                              const std::string& jwt_ = "", const std::string& username_ = "", | ||||
|                              const std::string& token_ = "") { | ||||
|         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()) { | ||||
|             LOG_ERROR(WebService, "Client is invalid, skipping request!"); | ||||
|             return {}; | ||||
|             LOG_ERROR(WebService, "Invalid URL {}", host + path); | ||||
|             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; | ||||
|         if (!jwt_.empty()) { | ||||
|             params = { | ||||
| @@ -107,15 +110,15 @@ struct Client::Impl { | ||||
|         request.headers = params; | ||||
|         request.body = data; | ||||
|  | ||||
|         httplib::Response response; | ||||
|         httplib::Error error; | ||||
|         httplib::Result result = cli->send(request); | ||||
|  | ||||
|         if (!cli->send(request, response, error)) { | ||||
|             LOG_ERROR(WebService, "{} to {} returned null (httplib Error: {})", method, host + path, | ||||
|                       httplib::to_string(error)); | ||||
|         if (!result) { | ||||
|             LOG_ERROR(WebService, "{} to {} returned null", method, host + path); | ||||
|             return WebResult{WebResult::Code::LibError, "Null response", ""}; | ||||
|         } | ||||
|  | ||||
|         httplib::Response response = result.value(); | ||||
|  | ||||
|         if (response.status >= 400) { | ||||
|             LOG_ERROR(WebService, "{} to {} returned error status code: {}", method, host + path, | ||||
|                       response.status); | ||||
|   | ||||
| @@ -248,82 +248,22 @@ void ConfigureUi::RetranslateUI() { | ||||
| } | ||||
|  | ||||
| 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{}); | ||||
|     QDir languages_dir{QStringLiteral(":/languages")}; | ||||
|     QStringList language_files = languages_dir.entryList(); | ||||
|     for (const auto& lang : languages) { | ||||
|         if (QString::fromLatin1(lang.id) == QStringLiteral("en")) { | ||||
|             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; | ||||
|     ui->language_combobox->addItem(tr("English"), QStringLiteral("en")); | ||||
|     QDirIterator it(QStringLiteral(":/languages"), QDirIterator::NoIteratorFlags); | ||||
|     while (it.hasNext()) { | ||||
|         QString locale = it.next(); | ||||
|         locale.truncate(locale.lastIndexOf(QLatin1Char{'.'})); | ||||
|         const QString language_name = QLocale::languageToString(QLocale(locale).language()); | ||||
|         const QString lang = QStringLiteral("%1 [%2]").arg(language_name, locale); | ||||
|         ui->language_combobox->addItem(lang, locale); | ||||
|         locale.remove(0, locale.lastIndexOf(QLatin1Char{'/'}) + 1); | ||||
|         const QString lang = QLocale::languageToString(QLocale(locale).language()); | ||||
|         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 | ||||
|     // interface immediately. This is done by passing a signal to the main window, and then | ||||
|     // 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); | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user