Let's make the rom list process on a separate thread so the emulator doesnt take ages to load.

This commit is contained in:
2026-06-12 15:30:47 +02:00
parent fc306967f9
commit 95d202f378
2 changed files with 75 additions and 47 deletions
+52 -40
View File
@@ -11,12 +11,28 @@
#include <Options.hpp> #include <Options.hpp>
#include <Scheduler.hpp> #include <Scheduler.hpp>
void KaizenGui::populateRomsList(const std::string &romsPath) { RomsListTable::RomsListTable() {
centralWidget->setCurrentWidget(romPathNotSet); verticalHeader()->hide();
if (!romsPath.empty()) { horizontalHeader()->setSectionResizeMode(QHeaderView::Interactive);
int i = 0; setSizePolicy({QSizePolicy::Maximum, QSizePolicy::Maximum});
centralWidget->setCurrentWidget(romsList); setSelectionMode(QAbstractItemView::SingleSelection);
setSelectionBehavior(QAbstractItemView::SelectRows);
setEditTriggers(QAbstractItemView::NoEditTriggers);
setSortingEnabled(true);
setColumnCount(4);
setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
setHorizontalHeaderItem(1, new QTableWidgetItem("Regions"));
setHorizontalHeaderItem(2, new QTableWidgetItem("Last played"));
setHorizontalHeaderItem(3, new QTableWidgetItem("Time played"));
std::jthread([&] {
populate(Options::GetRomsPath());
emit populateFinished();
});
}
void RomsListTable::populate(const std::string &romsPath) {
if (!romsPath.empty()) {
for (const auto &file : fs::recursive_directory_iterator{romsPath}) { for (const auto &file : fs::recursive_directory_iterator{romsPath}) {
if (!file.is_regular_file()) if (!file.is_regular_file())
continue; continue;
@@ -37,24 +53,12 @@ void KaizenGui::populateRomsList(const std::string &romsPath) {
auto regions = n64::GameDB::match(rom); auto regions = n64::GameDB::match(rom);
if (rom.gameNameDB.empty()) if (rom.gameNameDB.empty())
rom.gameNameDB = fs::path(filename).stem(); rom.gameNameDB = fs::path(filename).stem().string();
romsListPaths.push_back(filename); romsList.push_back(
romsList->insertRow(i); {rom.header.countryCode, rom.header.version, filename, rom.gameNameDB, regions, "Never", "0h 00m 00s"});
romsList->setItem(
i, 0,
new QTableWidgetItem(std::format("{} ({}) (Rev {})", rom.gameNameDB,
n64::GameDB::regionCodeToReadable(rom.header.countryCode),
rom.header.version)
.c_str()));
romsList->setItem(i, 1, new QTableWidgetItem(regions.c_str()));
romsList->setItem(i, 2, new QTableWidgetItem("Never"));
romsList->setItem(i, 3, new QTableWidgetItem("0h 0m 0s"));
i++;
} }
} }
currentHomeWidget = centralWidget->currentWidget();
} }
KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) { KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::UserScope) {
@@ -63,33 +67,40 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
SDL_AddGamepadMapping(gamecontrollerdb_str); SDL_AddGamepadMapping(gamecontrollerdb_str);
hide(); hide();
romsList->verticalHeader()->hide();
romsList->setSizePolicy({QSizePolicy::Maximum, QSizePolicy::Maximum});
romsList->setSelectionMode(QAbstractItemView::SingleSelection);
romsList->setSelectionBehavior(QAbstractItemView::SelectRows);
romsList->setEditTriggers(QAbstractItemView::NoEditTriggers);
romsList->setSortingEnabled(true);
romsList->setColumnCount(4);
romsList->setHorizontalHeaderItem(0, new QTableWidgetItem("Name"));
romsList->setHorizontalHeaderItem(1, new QTableWidgetItem("Regions"));
romsList->setHorizontalHeaderItem(2, new QTableWidgetItem("Last played"));
romsList->setHorizontalHeaderItem(3, new QTableWidgetItem("Time played"));
vulkanWidget = new RenderWidget(); vulkanWidget = new RenderWidget();
vulkanWidget->hide(); vulkanWidget->hide();
centralWidget->addWidget(vulkanWidget); centralWidget->addWidget(vulkanWidget);
centralWidget->addWidget(romsList); centralWidget->addWidget(romsListTable);
centralWidget->addWidget(romPathNotSet); centralWidget->addWidget(romPathNotSet);
populateRomsList(Options::GetRomsPath()); populateRomsListThread = QThread::create([&] {
populateRomsList(Options::GetRomsPath());
connect(romsList, &QTableWidget::cellDoubleClicked, this, [&](int row, int) { emit populateRomsListFinished();
auto fileToLoad = fs::path(Options::GetRomsPath()) / romsListPaths[row];
std::println("{}", fileToLoad.string());
LoadROM(fileToLoad.string());
}); });
populateRomsListThread->start();
connect(this, &KaizenGui::populateRomsListFinished, this, [&] {
for (int i = 0; i < romsList.size(); i++) {
const auto &[countryCode, version, _, name, regions, lastPlayed, timePlayed] = romsList[i];
romsListTable->insertRow(i);
romsListTable->setItem(
i, 0,
new QTableWidgetItem(
std::format("{} ({}) (Rev {})", name, n64::GameDB::regionCodeToReadable(countryCode), version)
.c_str()));
romsListTable->setItem(i, 1, new QTableWidgetItem(regions.c_str()));
romsListTable->setItem(i, 2, new QTableWidgetItem(lastPlayed.c_str()));
romsListTable->setItem(i, 3, new QTableWidgetItem(timePlayed.c_str()));
}
});
connect(this, &KaizenGui::romsListNeedsPopulation, this, [&] { populateRomsListThread->start(); });
connect(romsListTable, &QTableWidget::cellDoubleClicked, this, [&](int row, int) { LoadROM(romsList[row].path); });
installEventFilter(this); installEventFilter(this);
restoreGeometry(settings.value("geometry").toByteArray()); restoreGeometry(settings.value("geometry").toByteArray());
@@ -112,6 +123,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
setWindowTitle("Kaizen " KAIZEN_VERSION_STR); setWindowTitle("Kaizen " KAIZEN_VERSION_STR);
setMinimumSize(640, 480); setMinimumSize(640, 480);
setCentralWidget(centralWidget); setCentralWidget(centralWidget);
centralWidget->setLayout(new QVBoxLayout());
setAcceptDrops(true); setAcceptDrops(true);
@@ -184,7 +196,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
settingsWindow = new SettingsWindow(); settingsWindow = new SettingsWindow();
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show); connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
connect(settingsWindow->general, &GeneralSettings::romFolderSelected, this, connect(settingsWindow->general, &GeneralSettings::romFolderSelected, this,
[&] { populateRomsList(Options::GetRomsPath()); }); [&] { emit romsListNeedsPopulation(); });
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] { connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
core.cpuType = Options::GetCpuType(); core.cpuType = Options::GetCpuType();
+23 -7
View File
@@ -13,17 +13,35 @@
class EmuThread; class EmuThread;
struct RomsListEntry {
u8 countryCode, version;
std::string path;
std::string name;
std::string region;
std::string lastPlayed;
std::string timePlayed;
};
class RomsListTable : public QTableWidget {
Q_OBJECT
std::vector<RomsListEntry> romsList;
public:
RomsListTable();
public slots:
void populate(const std::string &);
signals:
void populateFinished();
};
class KaizenGui final : QMainWindow { class KaizenGui final : QMainWindow {
Q_OBJECT Q_OBJECT
void updateKeys(); void updateKeys();
void updateAxis(); void updateAxis();
bool eventFilter(QObject *, QEvent *) override; bool eventFilter(QObject *, QEvent *) override;
void populateRomsList(const std::string &);
bool fastForward = false; bool fastForward = false;
bool minimized = false; bool minimized = false;
std::vector<std::string> romsListPaths{};
SDL_Gamepad *gamepad = nullptr; SDL_Gamepad *gamepad = nullptr;
bool gamepadConnected; bool gamepadConnected;
float elapsed = 0.f; float elapsed = 0.f;
@@ -33,12 +51,12 @@ class KaizenGui final : QMainWindow {
QWidget *currentHomeWidget; QWidget *currentHomeWidget;
QLabel *romPathNotSet = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")"); QLabel *romPathNotSet = new QLabel(R"(Kaizen could not find any ROMs. Set the path in "Settings -> General")");
QTableWidget *romsList = new QTableWidget(); RomsListTable *romsListTable = new RomsListTable();
QStackedWidget *centralWidget = new QStackedWidget(); QStackedWidget *centralWidget = new QStackedWidget();
SettingsWindow *settingsWindow; SettingsWindow *settingsWindow;
RenderWidget *vulkanWidget; RenderWidget *vulkanWidget;
QSettings settings; QSettings settings;
QThread *emuThread; QThread *emuThread, *populateRomsListThread;
QTimer *statusBarTimer, *SDLeventsTimer; QTimer *statusBarTimer, *SDLeventsTimer;
QLabel *fpsLabel; QLabel *fpsLabel;
QLabel *cpuTypeLabel; QLabel *cpuTypeLabel;
@@ -59,6 +77,4 @@ class KaizenGui final : QMainWindow {
void LoadTAS(const std::string &path) noexcept; void LoadTAS(const std::string &path) noexcept;
void LoadROM(const std::string &path) noexcept; void LoadROM(const std::string &path) noexcept;
signals:
void paused();
}; };