early-access version 4154
This commit is contained in:
parent
742bf25252
commit
64bd48fad5
10 changed files with 114 additions and 40 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 4153.
|
This is the source code for early-access 4154.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,9 @@ abstract class SettingsItem(
|
||||||
get() = NativeLibrary.isRunning() && !setting.global &&
|
get() = NativeLibrary.isRunning() && !setting.global &&
|
||||||
!NativeConfig.isPerGameConfigLoaded()
|
!NativeConfig.isPerGameConfigLoaded()
|
||||||
|
|
||||||
|
val clearable: Boolean
|
||||||
|
get() = !setting.global && NativeConfig.isPerGameConfigLoaded()
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val TYPE_HEADER = 0
|
const val TYPE_HEADER = 0
|
||||||
const val TYPE_SWITCH = 1
|
const val TYPE_SWITCH = 1
|
||||||
|
|
|
@ -13,7 +13,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.DateTimeSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||||
|
|
||||||
class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||||
|
@ -32,9 +31,7 @@ class DateTimeViewHolder(val binding: ListItemSettingBinding, adapter: SettingsA
|
||||||
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
val dateFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
|
||||||
binding.textSettingValue.text = dateFormatter.format(zonedTime)
|
binding.textSettingValue.text = dateFormatter.format(zonedTime)
|
||||||
|
|
||||||
binding.buttonClear.setVisible(
|
binding.buttonClear.setVisible(setting.clearable)
|
||||||
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
|
|
||||||
)
|
|
||||||
binding.buttonClear.setOnClickListener {
|
binding.buttonClear.setOnClickListener {
|
||||||
adapter.onClearClick(setting, bindingAdapterPosition)
|
adapter.onClearClick(setting, bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.SingleChoiceSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.StringSingleChoiceSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||||
|
|
||||||
class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||||
|
@ -48,9 +47,7 @@ class SingleChoiceViewHolder(val binding: ListItemSettingBinding, adapter: Setti
|
||||||
binding.textSettingValue.setVisible(false)
|
binding.textSettingValue.setVisible(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.buttonClear.setVisible(
|
binding.buttonClear.setVisible(setting.clearable)
|
||||||
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
|
|
||||||
)
|
|
||||||
binding.buttonClear.setOnClickListener {
|
binding.buttonClear.setOnClickListener {
|
||||||
adapter.onClearClick(setting, bindingAdapterPosition)
|
adapter.onClearClick(setting, bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.SliderSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||||
|
|
||||||
class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAdapter) :
|
||||||
|
@ -28,9 +27,7 @@ class SliderViewHolder(val binding: ListItemSettingBinding, adapter: SettingsAda
|
||||||
setting.units
|
setting.units
|
||||||
)
|
)
|
||||||
|
|
||||||
binding.buttonClear.setVisible(
|
binding.buttonClear.setVisible(setting.clearable)
|
||||||
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
|
|
||||||
)
|
|
||||||
binding.buttonClear.setOnClickListener {
|
binding.buttonClear.setOnClickListener {
|
||||||
adapter.onClearClick(setting, bindingAdapterPosition)
|
adapter.onClearClick(setting, bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@ import org.yuzu.yuzu_emu.databinding.ListItemSettingSwitchBinding
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
import org.yuzu.yuzu_emu.features.settings.model.view.SettingsItem
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting
|
import org.yuzu.yuzu_emu.features.settings.model.view.SwitchSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
import org.yuzu.yuzu_emu.features.settings.ui.SettingsAdapter
|
||||||
import org.yuzu.yuzu_emu.utils.NativeConfig
|
|
||||||
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
import org.yuzu.yuzu_emu.utils.ViewUtils.setVisible
|
||||||
|
|
||||||
class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) :
|
class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter: SettingsAdapter) :
|
||||||
|
@ -29,9 +28,7 @@ class SwitchSettingViewHolder(val binding: ListItemSettingSwitchBinding, adapter
|
||||||
adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition)
|
adapter.onBooleanClick(setting, binding.switchWidget.isChecked, bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.buttonClear.setVisible(
|
binding.buttonClear.setVisible(setting.clearable)
|
||||||
!setting.setting.global || NativeConfig.isPerGameConfigLoaded()
|
|
||||||
)
|
|
||||||
binding.buttonClear.setOnClickListener {
|
binding.buttonClear.setOnClickListener {
|
||||||
adapter.onClearClick(setting, bindingAdapterPosition)
|
adapter.onClearClick(setting, bindingAdapterPosition)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.yuzu.yuzu_emu.features.input.NativeInput
|
||||||
import org.yuzu.yuzu_emu.R
|
import org.yuzu.yuzu_emu.R
|
||||||
import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
|
import org.yuzu.yuzu_emu.features.input.model.NativeAnalog
|
||||||
import org.yuzu.yuzu_emu.features.input.model.NativeButton
|
import org.yuzu.yuzu_emu.features.input.model.NativeButton
|
||||||
|
import org.yuzu.yuzu_emu.features.input.model.NpadStyleIndex
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
import org.yuzu.yuzu_emu.features.settings.model.BooleanSetting
|
||||||
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
import org.yuzu.yuzu_emu.features.settings.model.IntSetting
|
||||||
import org.yuzu.yuzu_emu.overlay.model.OverlayControl
|
import org.yuzu.yuzu_emu.overlay.model.OverlayControl
|
||||||
|
@ -99,11 +100,9 @@ class InputOverlay(context: Context, attrs: AttributeSet?) :
|
||||||
}
|
}
|
||||||
|
|
||||||
var shouldUpdateView = false
|
var shouldUpdateView = false
|
||||||
val playerIndex =
|
val playerIndex = when (NativeInput.getStyleIndex(0)) {
|
||||||
if (NativeInput.isHandheldOnly()) {
|
NpadStyleIndex.Handheld -> 8
|
||||||
NativeInput.ConsoleDevice
|
else -> 0
|
||||||
} else {
|
|
||||||
NativeInput.Player1Device
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (button in overlayButtons) {
|
for (button in overlayButtons) {
|
||||||
|
|
|
@ -1604,6 +1604,7 @@ void GMainWindow::ConnectMenuEvents() {
|
||||||
connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder);
|
connect_menu(ui->action_Open_yuzu_Folder, &GMainWindow::OnOpenYuzuFolder);
|
||||||
connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents);
|
connect_menu(ui->action_Verify_installed_contents, &GMainWindow::OnVerifyInstalledContents);
|
||||||
connect_menu(ui->action_Install_Firmware, &GMainWindow::OnInstallFirmware);
|
connect_menu(ui->action_Install_Firmware, &GMainWindow::OnInstallFirmware);
|
||||||
|
connect_menu(ui->action_Install_Keys, &GMainWindow::OnInstallDecryptionKeys);
|
||||||
connect_menu(ui->action_About, &GMainWindow::OnAbout);
|
connect_menu(ui->action_About, &GMainWindow::OnAbout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1633,6 +1634,7 @@ void GMainWindow::UpdateMenuState() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ui->action_Install_Firmware->setEnabled(!emulation_running);
|
ui->action_Install_Firmware->setEnabled(!emulation_running);
|
||||||
|
ui->action_Install_Keys->setEnabled(!emulation_running);
|
||||||
|
|
||||||
for (QAction* action : applet_actions) {
|
for (QAction* action : applet_actions) {
|
||||||
action->setEnabled(is_firmware_available && !emulation_running);
|
action->setEnabled(is_firmware_available && !emulation_running);
|
||||||
|
@ -4169,9 +4171,8 @@ void GMainWindow::OnInstallFirmware() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString firmware_source_location =
|
const QString firmware_source_location = QFileDialog::getExistingDirectory(
|
||||||
QFileDialog::getExistingDirectory(this, tr("Select Dumped Firmware Source Location"),
|
this, tr("Select Dumped Firmware Source Location"), {}, QFileDialog::ShowDirsOnly);
|
||||||
QString::fromStdString(""), QFileDialog::ShowDirsOnly);
|
|
||||||
if (firmware_source_location.isEmpty()) {
|
if (firmware_source_location.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -4202,8 +4203,9 @@ void GMainWindow::OnInstallFirmware() {
|
||||||
std::vector<std::filesystem::path> out;
|
std::vector<std::filesystem::path> out;
|
||||||
const Common::FS::DirEntryCallable callback =
|
const Common::FS::DirEntryCallable callback =
|
||||||
[&out](const std::filesystem::directory_entry& entry) {
|
[&out](const std::filesystem::directory_entry& entry) {
|
||||||
if (entry.path().has_extension() && entry.path().extension() == ".nca")
|
if (entry.path().has_extension() && entry.path().extension() == ".nca") {
|
||||||
out.emplace_back(entry.path());
|
out.emplace_back(entry.path());
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
@ -4235,7 +4237,6 @@ void GMainWindow::OnInstallFirmware() {
|
||||||
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
|
auto firmware_vdir = sysnand_content_vdir->GetDirectoryRelative("registered");
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
bool cancelled = false;
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const auto& firmware_src_path : out) {
|
for (const auto& firmware_src_path : out) {
|
||||||
i++;
|
i++;
|
||||||
|
@ -4250,24 +4251,22 @@ void GMainWindow::OnInstallFirmware() {
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (QtProgressCallback(100, 20 + (int)(((float)(i) / (float)out.size()) * 70.0))) {
|
if (QtProgressCallback(
|
||||||
success = false;
|
100, 20 + static_cast<int>(((i) / static_cast<float>(out.size())) * 70.0))) {
|
||||||
cancelled = true;
|
progress.close();
|
||||||
break;
|
QMessageBox::warning(
|
||||||
|
this, tr("Firmware install failed"),
|
||||||
|
tr("Firmware installation cancelled, firmware may be in bad state, "
|
||||||
|
"restart yuzu or re-install firmware."));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!success && !cancelled) {
|
if (!success) {
|
||||||
progress.close();
|
progress.close();
|
||||||
QMessageBox::critical(this, tr("Firmware install failed"),
|
QMessageBox::critical(this, tr("Firmware install failed"),
|
||||||
tr("One or more firmware files failed to copy into NAND."));
|
tr("One or more firmware files failed to copy into NAND."));
|
||||||
return;
|
return;
|
||||||
} else if (cancelled) {
|
|
||||||
progress.close();
|
|
||||||
QMessageBox::warning(this, tr("Firmware install failed"),
|
|
||||||
tr("Firmware installation cancelled, firmware may be in bad state, "
|
|
||||||
"restart yuzu or re-install firmware."));
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Re-scan VFS for the newly placed firmware files.
|
// Re-scan VFS for the newly placed firmware files.
|
||||||
|
@ -4295,6 +4294,84 @@ void GMainWindow::OnInstallFirmware() {
|
||||||
OnCheckFirmwareDecryption();
|
OnCheckFirmwareDecryption();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GMainWindow::OnInstallDecryptionKeys() {
|
||||||
|
// Don't do this while emulation is running.
|
||||||
|
if (emu_thread != nullptr && emu_thread->IsRunning()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString key_source_location = QFileDialog::getOpenFileName(
|
||||||
|
this, tr("Select Dumped Keys Location"), {}, QStringLiteral("prod.keys (prod.keys)"), {},
|
||||||
|
QFileDialog::ReadOnly);
|
||||||
|
if (key_source_location.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that it contains prod.keys, title.keys and optionally, key_retail.bin
|
||||||
|
LOG_INFO(Frontend, "Installing key files from {}", key_source_location.toStdString());
|
||||||
|
|
||||||
|
const std::filesystem::path prod_key_path = key_source_location.toStdString();
|
||||||
|
const std::filesystem::path key_source_path = prod_key_path.parent_path();
|
||||||
|
if (!Common::FS::IsDir(key_source_path)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool prod_keys_found = false;
|
||||||
|
std::vector<std::filesystem::path> source_key_files;
|
||||||
|
|
||||||
|
if (Common::FS::Exists(prod_key_path)) {
|
||||||
|
prod_keys_found = true;
|
||||||
|
source_key_files.emplace_back(prod_key_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Common::FS::Exists(key_source_path / "title.keys")) {
|
||||||
|
source_key_files.emplace_back(key_source_path / "title.keys");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Common::FS::Exists(key_source_path / "key_retail.bin")) {
|
||||||
|
source_key_files.emplace_back(key_source_path / "key_retail.bin");
|
||||||
|
}
|
||||||
|
|
||||||
|
// There should be at least prod.keys.
|
||||||
|
if (source_key_files.empty() || !prod_keys_found) {
|
||||||
|
QMessageBox::warning(this, tr("Decryption Keys install failed"),
|
||||||
|
tr("prod.keys is a required decryption key file."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto yuzu_keys_dir = Common::FS::GetYuzuPath(Common::FS::YuzuPath::KeysDir);
|
||||||
|
for (auto key_file : source_key_files) {
|
||||||
|
std::filesystem::path destination_key_file = yuzu_keys_dir / key_file.filename();
|
||||||
|
if (!std::filesystem::copy_file(key_file, destination_key_file,
|
||||||
|
std::filesystem::copy_options::overwrite_existing)) {
|
||||||
|
LOG_ERROR(Frontend, "Failed to copy file {} to {}", key_file.string(),
|
||||||
|
destination_key_file.string());
|
||||||
|
QMessageBox::critical(this, tr("Decryption Keys install failed"),
|
||||||
|
tr("One or more keys failed to copy."));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reinitialize the key manager, re-read the vfs (for update/dlc files),
|
||||||
|
// and re-populate the game list in the UI if the user has already added
|
||||||
|
// game folders.
|
||||||
|
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
||||||
|
system->GetFileSystemController().CreateFactories(*vfs);
|
||||||
|
game_list->PopulateAsync(UISettings::values.game_dirs);
|
||||||
|
|
||||||
|
if (ContentManager::AreKeysPresent()) {
|
||||||
|
QMessageBox::information(this, tr("Decryption Keys install succeeded"),
|
||||||
|
tr("Decryption Keys were successfully installed"));
|
||||||
|
} else {
|
||||||
|
QMessageBox::critical(
|
||||||
|
this, tr("Decryption Keys install failed"),
|
||||||
|
tr("Decryption Keys failed to initialize. Check that your dumping tools are "
|
||||||
|
"up to date and re-dump keys."));
|
||||||
|
}
|
||||||
|
|
||||||
|
OnCheckFirmwareDecryption();
|
||||||
|
}
|
||||||
|
|
||||||
void GMainWindow::OnAbout() {
|
void GMainWindow::OnAbout() {
|
||||||
AboutDialog aboutDialog(this);
|
AboutDialog aboutDialog(this);
|
||||||
aboutDialog.exec();
|
aboutDialog.exec();
|
||||||
|
|
|
@ -381,6 +381,7 @@ private slots:
|
||||||
void OnOpenYuzuFolder();
|
void OnOpenYuzuFolder();
|
||||||
void OnVerifyInstalledContents();
|
void OnVerifyInstalledContents();
|
||||||
void OnInstallFirmware();
|
void OnInstallFirmware();
|
||||||
|
void OnInstallDecryptionKeys();
|
||||||
void OnAbout();
|
void OnAbout();
|
||||||
void OnToggleFilterBar();
|
void OnToggleFilterBar();
|
||||||
void OnToggleStatusBar();
|
void OnToggleStatusBar();
|
||||||
|
|
|
@ -165,8 +165,9 @@
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="action_Configure_Tas"/>
|
<addaction name="action_Configure_Tas"/>
|
||||||
</widget>
|
</widget>
|
||||||
<addaction name="action_Verify_installed_contents"/>
|
<addaction name="action_Install_Keys"/>
|
||||||
<addaction name="action_Install_Firmware"/>
|
<addaction name="action_Install_Firmware"/>
|
||||||
|
<addaction name="action_Verify_installed_contents"/>
|
||||||
<addaction name="separator"/>
|
<addaction name="separator"/>
|
||||||
<addaction name="menu_cabinet_applet"/>
|
<addaction name="menu_cabinet_applet"/>
|
||||||
<addaction name="action_Load_Album"/>
|
<addaction name="action_Load_Album"/>
|
||||||
|
@ -469,6 +470,11 @@
|
||||||
<string>Install Firmware</string>
|
<string>Install Firmware</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="action_Install_Keys">
|
||||||
|
<property name="text">
|
||||||
|
<string>Install Decryption Keys</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<resources>
|
<resources>
|
||||||
<include location="yuzu.qrc"/>
|
<include location="yuzu.qrc"/>
|
||||||
|
|
Loading…
Reference in a new issue