Merge branch 'master' into feature/savestates-2
This commit is contained in:
@@ -25,10 +25,6 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
|
||||
ConfigureGeneral::~ConfigureGeneral() = default;
|
||||
|
||||
void ConfigureGeneral::SetConfiguration() {
|
||||
ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit);
|
||||
ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked());
|
||||
ui->frame_limit->setValue(Settings::values.frame_limit);
|
||||
|
||||
ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
|
||||
ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background);
|
||||
|
||||
@@ -57,9 +53,6 @@ void ConfigureGeneral::ResetDefaults() {
|
||||
}
|
||||
|
||||
void ConfigureGeneral::ApplyConfiguration() {
|
||||
Settings::values.use_frame_limit = ui->toggle_frame_limit->isChecked();
|
||||
Settings::values.frame_limit = ui->frame_limit->value();
|
||||
|
||||
UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked();
|
||||
UISettings::values.pause_when_in_background = ui->toggle_background_pause->isChecked();
|
||||
|
||||
|
@@ -114,7 +114,7 @@ void IPCRecorderWidget::SetEnabled(bool enabled) {
|
||||
}
|
||||
|
||||
void IPCRecorderWidget::Clear() {
|
||||
id_offset = records.size() + 1;
|
||||
id_offset += records.size();
|
||||
|
||||
records.clear();
|
||||
ui->main->invisibleRootItem()->takeChildren();
|
||||
|
@@ -61,13 +61,14 @@ void RegistersWidget::OnDebugModeEntered() {
|
||||
if (!Core::System::GetInstance().IsPoweredOn())
|
||||
return;
|
||||
|
||||
// Todo: Handle all cores
|
||||
for (int i = 0; i < core_registers->childCount(); ++i)
|
||||
core_registers->child(i)->setText(
|
||||
1, QStringLiteral("0x%1").arg(Core::CPU().GetReg(i), 8, 16, QLatin1Char('0')));
|
||||
1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetReg(i), 8, 16, QLatin1Char('0')));
|
||||
|
||||
for (int i = 0; i < vfp_registers->childCount(); ++i)
|
||||
vfp_registers->child(i)->setText(
|
||||
1, QStringLiteral("0x%1").arg(Core::CPU().GetVFPReg(i), 8, 16, QLatin1Char('0')));
|
||||
1, QStringLiteral("0x%1").arg(Core::GetCore(0).GetVFPReg(i), 8, 16, QLatin1Char('0')));
|
||||
|
||||
UpdateCPSRValues();
|
||||
UpdateVFPSystemRegisterValues();
|
||||
@@ -127,7 +128,8 @@ void RegistersWidget::CreateCPSRChildren() {
|
||||
}
|
||||
|
||||
void RegistersWidget::UpdateCPSRValues() {
|
||||
const u32 cpsr_val = Core::CPU().GetCPSR();
|
||||
// Todo: Handle all cores
|
||||
const u32 cpsr_val = Core::GetCore(0).GetCPSR();
|
||||
|
||||
cpsr->setText(1, QStringLiteral("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
|
||||
cpsr->child(0)->setText(
|
||||
@@ -191,10 +193,11 @@ void RegistersWidget::CreateVFPSystemRegisterChildren() {
|
||||
}
|
||||
|
||||
void RegistersWidget::UpdateVFPSystemRegisterValues() {
|
||||
const u32 fpscr_val = Core::CPU().GetVFPSystemReg(VFP_FPSCR);
|
||||
const u32 fpexc_val = Core::CPU().GetVFPSystemReg(VFP_FPEXC);
|
||||
const u32 fpinst_val = Core::CPU().GetVFPSystemReg(VFP_FPINST);
|
||||
const u32 fpinst2_val = Core::CPU().GetVFPSystemReg(VFP_FPINST2);
|
||||
// Todo: handle all cores
|
||||
const u32 fpscr_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPSCR);
|
||||
const u32 fpexc_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPEXC);
|
||||
const u32 fpinst_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPINST);
|
||||
const u32 fpinst2_val = Core::GetCore(0).GetVFPSystemReg(VFP_FPINST2);
|
||||
|
||||
QTreeWidgetItem* const fpscr = vfp_system_registers->child(0);
|
||||
fpscr->setText(1, QStringLiteral("0x%1").arg(fpscr_val, 8, 16, QLatin1Char('0')));
|
||||
|
@@ -12,6 +12,7 @@
|
||||
#include "core/hle/kernel/thread.h"
|
||||
#include "core/hle/kernel/timer.h"
|
||||
#include "core/hle/kernel/wait_object.h"
|
||||
#include "core/settings.h"
|
||||
|
||||
WaitTreeItem::~WaitTreeItem() = default;
|
||||
|
||||
@@ -51,12 +52,16 @@ std::size_t WaitTreeItem::Row() const {
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
|
||||
const auto& threads = Core::System::GetInstance().Kernel().GetThreadManager().GetThreadList();
|
||||
u32 num_cores = Core::GetNumCores();
|
||||
std::vector<std::unique_ptr<WaitTreeThread>> item_list;
|
||||
item_list.reserve(threads.size());
|
||||
for (std::size_t i = 0; i < threads.size(); ++i) {
|
||||
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i]));
|
||||
item_list.back()->row = i;
|
||||
for (u32 i = 0; i < num_cores; ++i) {
|
||||
const auto& threads =
|
||||
Core::System::GetInstance().Kernel().GetThreadManager(i).GetThreadList();
|
||||
item_list.reserve(item_list.size() + threads.size());
|
||||
for (std::size_t i = 0; i < threads.size(); ++i) {
|
||||
item_list.push_back(std::make_unique<WaitTreeThread>(*threads[i]));
|
||||
item_list.back()->row = i;
|
||||
}
|
||||
}
|
||||
return item_list;
|
||||
}
|
||||
|
@@ -468,6 +468,8 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
|
||||
QAction* open_texture_dump_location = context_menu.addAction(tr("Open Texture Dump Location"));
|
||||
QAction* open_texture_load_location =
|
||||
context_menu.addAction(tr("Open Custom Texture Location"));
|
||||
QAction* open_mods_location = context_menu.addAction(tr("Open Mods Location"));
|
||||
QAction* dump_romfs = context_menu.addAction(tr("Dump RomFS"));
|
||||
QAction* navigate_to_gamedb_entry = context_menu.addAction(tr("Navigate to GameDB entry"));
|
||||
|
||||
const bool is_application =
|
||||
@@ -497,6 +499,8 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
|
||||
|
||||
open_texture_dump_location->setVisible(is_application);
|
||||
open_texture_load_location->setVisible(is_application);
|
||||
open_mods_location->setVisible(is_application);
|
||||
dump_romfs->setVisible(is_application);
|
||||
|
||||
navigate_to_gamedb_entry->setVisible(it != compatibility_list.end());
|
||||
|
||||
@@ -526,6 +530,15 @@ void GameList::AddGamePopup(QMenu& context_menu, const QString& path, u64 progra
|
||||
emit OpenFolderRequested(program_id, GameListOpenTarget::TEXTURE_LOAD);
|
||||
}
|
||||
});
|
||||
connect(open_mods_location, &QAction::triggered, [this, program_id] {
|
||||
if (FileUtil::CreateFullPath(fmt::format("{}mods/{:016X}/",
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
|
||||
program_id))) {
|
||||
emit OpenFolderRequested(program_id, GameListOpenTarget::MODS);
|
||||
}
|
||||
});
|
||||
connect(dump_romfs, &QAction::triggered,
|
||||
[this, path, program_id] { emit DumpRomFSRequested(path, program_id); });
|
||||
connect(navigate_to_gamedb_entry, &QAction::triggered, [this, program_id]() {
|
||||
emit NavigateToGamedbEntryRequested(program_id, compatibility_list);
|
||||
});
|
||||
|
@@ -35,7 +35,8 @@ enum class GameListOpenTarget {
|
||||
APPLICATION = 2,
|
||||
UPDATE_DATA = 3,
|
||||
TEXTURE_DUMP = 4,
|
||||
TEXTURE_LOAD = 5
|
||||
TEXTURE_LOAD = 5,
|
||||
MODS = 6,
|
||||
};
|
||||
|
||||
class GameList : public QWidget {
|
||||
@@ -81,6 +82,7 @@ signals:
|
||||
void OpenFolderRequested(u64 program_id, GameListOpenTarget target);
|
||||
void NavigateToGamedbEntryRequested(u64 program_id,
|
||||
const CompatibilityList& compatibility_list);
|
||||
void DumpRomFSRequested(QString game_path, u64 program_id);
|
||||
void OpenDirectory(const QString& directory);
|
||||
void AddDirectory();
|
||||
void ShowList(bool show);
|
||||
|
@@ -597,6 +597,7 @@ void GMainWindow::ConnectWidgetEvents() {
|
||||
connect(game_list, &GameList::OpenFolderRequested, this, &GMainWindow::OnGameListOpenFolder);
|
||||
connect(game_list, &GameList::NavigateToGamedbEntryRequested, this,
|
||||
&GMainWindow::OnGameListNavigateToGamedbEntry);
|
||||
connect(game_list, &GameList::DumpRomFSRequested, this, &GMainWindow::OnGameListDumpRomFS);
|
||||
connect(game_list, &GameList::AddDirectory, this, &GMainWindow::OnGameListAddDirectory);
|
||||
connect(game_list_placeholder, &GameListPlaceholder::AddDirectory, this,
|
||||
&GMainWindow::OnGameListAddDirectory);
|
||||
@@ -1231,6 +1232,11 @@ void GMainWindow::OnGameListOpenFolder(u64 data_id, GameListOpenTarget target) {
|
||||
path = fmt::format("{}textures/{:016X}/",
|
||||
FileUtil::GetUserPath(FileUtil::UserPath::LoadDir), data_id);
|
||||
break;
|
||||
case GameListOpenTarget::MODS:
|
||||
open_target = "Mods";
|
||||
path = fmt::format("{}mods/{:016X}/", FileUtil::GetUserPath(FileUtil::UserPath::LoadDir),
|
||||
data_id);
|
||||
break;
|
||||
default:
|
||||
LOG_ERROR(Frontend, "Unexpected target {}", static_cast<int>(target));
|
||||
return;
|
||||
@@ -1262,6 +1268,46 @@ void GMainWindow::OnGameListNavigateToGamedbEntry(u64 program_id,
|
||||
QDesktopServices::openUrl(QUrl(QStringLiteral("https://citra-emu.org/game/") + directory));
|
||||
}
|
||||
|
||||
void GMainWindow::OnGameListDumpRomFS(QString game_path, u64 program_id) {
|
||||
auto* dialog = new QProgressDialog(tr("Dumping..."), tr("Cancel"), 0, 0, this);
|
||||
dialog->setWindowModality(Qt::WindowModal);
|
||||
dialog->setWindowFlags(dialog->windowFlags() &
|
||||
~(Qt::WindowCloseButtonHint | Qt::WindowContextHelpButtonHint));
|
||||
dialog->setCancelButton(nullptr);
|
||||
dialog->setMinimumDuration(0);
|
||||
dialog->setValue(0);
|
||||
|
||||
const auto base_path = fmt::format(
|
||||
"{}romfs/{:016X}", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir), program_id);
|
||||
const auto update_path =
|
||||
fmt::format("{}romfs/{:016X}", FileUtil::GetUserPath(FileUtil::UserPath::DumpDir),
|
||||
program_id | 0x0004000e00000000);
|
||||
using FutureWatcher = QFutureWatcher<std::pair<Loader::ResultStatus, Loader::ResultStatus>>;
|
||||
auto* future_watcher = new FutureWatcher(this);
|
||||
connect(future_watcher, &FutureWatcher::finished,
|
||||
[this, program_id, dialog, base_path, update_path, future_watcher] {
|
||||
dialog->hide();
|
||||
const auto& [base, update] = future_watcher->result();
|
||||
if (base != Loader::ResultStatus::Success) {
|
||||
QMessageBox::critical(
|
||||
this, tr("Citra"),
|
||||
tr("Could not dump base RomFS.\nRefer to the log for details."));
|
||||
return;
|
||||
}
|
||||
QDesktopServices::openUrl(QUrl::fromLocalFile(QString::fromStdString(base_path)));
|
||||
if (update == Loader::ResultStatus::Success) {
|
||||
QDesktopServices::openUrl(
|
||||
QUrl::fromLocalFile(QString::fromStdString(update_path)));
|
||||
}
|
||||
});
|
||||
|
||||
auto future = QtConcurrent::run([game_path, base_path, update_path] {
|
||||
std::unique_ptr<Loader::AppLoader> loader = Loader::GetLoader(game_path.toStdString());
|
||||
return std::make_pair(loader->DumpRomFS(base_path), loader->DumpUpdateRomFS(update_path));
|
||||
});
|
||||
future_watcher->setFuture(future);
|
||||
}
|
||||
|
||||
void GMainWindow::OnGameListOpenDirectory(const QString& directory) {
|
||||
QString path;
|
||||
if (directory == QStringLiteral("INSTALLED")) {
|
||||
|
@@ -176,6 +176,7 @@ private slots:
|
||||
void OnGameListOpenFolder(u64 program_id, GameListOpenTarget target);
|
||||
void OnGameListNavigateToGamedbEntry(u64 program_id,
|
||||
const CompatibilityList& compatibility_list);
|
||||
void OnGameListDumpRomFS(QString game_path, u64 program_id);
|
||||
void OnGameListOpenDirectory(const QString& directory);
|
||||
void OnGameListAddDirectory();
|
||||
void OnGameListShowList(bool show);
|
||||
|
Reference in New Issue
Block a user