Qt6 frontend #1
+2
-2
@@ -151,14 +151,14 @@ set(CAPSTONE_MIPS_SUPPORT ON)
|
||||
set(CAPSTONE_X86_SUPPORT ON)
|
||||
add_subdirectory(external/capstone)
|
||||
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
qt_add_executable(kaizen
|
||||
src/frontend/main.cpp
|
||||
src/frontend/KaizenGui.hpp
|
||||
src/frontend/KaizenGui.cpp
|
||||
src/frontend/RenderWidget.cpp
|
||||
src/frontend/RenderWidget.hpp
|
||||
src/frontend/EmuThread.hpp
|
||||
src/frontend/EmuThread.cpp
|
||||
src/frontend/SettingsWindow.hpp
|
||||
src/frontend/SettingsWindow.cpp
|
||||
src/frontend/Settings/GeneralSettings.hpp
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
namespace n64 {
|
||||
Core::Core() : interpreter(*mem, regs) {
|
||||
const auto selectedCpu = Options::GetCpuType();
|
||||
if (selectedCpu == "interpreter") {
|
||||
if (selectedCpu == 0) {
|
||||
cpuType = PlainInterpreter;
|
||||
} else if (selectedCpu == "cached_interpreter") {
|
||||
} else if (selectedCpu == 1) {
|
||||
cpuType = CachedInterpreter;
|
||||
} else {
|
||||
panic("Unimplemented CPU type");
|
||||
|
||||
@@ -32,13 +32,24 @@ void Scheduler::SkipToNext() { ticks = events.top().time; }
|
||||
void Scheduler::Tick(const u64 t) { ticks += t; }
|
||||
|
||||
void Scheduler::HandleEvents() {
|
||||
n64::Mem &mem = n64::Core::GetMem();
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
n64::Mem &mem = core.GetMem();
|
||||
n64::MI &mi = mem.mmio.mi;
|
||||
n64::SI &si = mem.mmio.si;
|
||||
n64::PI &pi = mem.mmio.pi;
|
||||
|
||||
while (ticks >= events.top().time) {
|
||||
switch (const auto type = events.top().type) {
|
||||
case PAUSE:
|
||||
core.TogglePause();
|
||||
break;
|
||||
case STOP:
|
||||
core.Stop();
|
||||
core.rom = {};
|
||||
break;
|
||||
case RESET:
|
||||
core.Reset();
|
||||
break;
|
||||
case SI_DMA:
|
||||
si.DMA();
|
||||
break;
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
#include <log.hpp>
|
||||
#include <queue>
|
||||
|
||||
enum EventType { NONE, PI_BUS_WRITE_COMPLETE, PI_DMA_COMPLETE, SI_DMA, IMPOSSIBLE };
|
||||
enum EventType { NONE, PAUSE, STOP, RESET, PI_BUS_WRITE_COMPLETE, PI_DMA_COMPLETE, SI_DMA, IMPOSSIBLE };
|
||||
|
||||
struct Event {
|
||||
u64 time;
|
||||
|
||||
@@ -1,25 +0,0 @@
|
||||
#include <EmuThread.hpp>
|
||||
#include <KaizenGui.hpp>
|
||||
#include <Core.hpp>
|
||||
|
||||
EmuThread::EmuThread() noexcept {}
|
||||
|
||||
void EmuThread::run() const noexcept {
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
if (!core.romLoaded)
|
||||
return;
|
||||
|
||||
if (!core.pause) {
|
||||
core.Run();
|
||||
}
|
||||
}
|
||||
|
||||
void EmuThread::TogglePause() const noexcept { n64::Core::GetInstance().TogglePause(); }
|
||||
|
||||
void EmuThread::Reset() const noexcept { n64::Core::GetInstance().Reset(); }
|
||||
|
||||
void EmuThread::Stop() const noexcept {
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
core.Stop();
|
||||
core.rom = {};
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
#pragma once
|
||||
#include <RenderWidget.hpp>
|
||||
#include <SettingsWindow.hpp>
|
||||
#include <memory>
|
||||
|
||||
namespace n64 {
|
||||
struct Core;
|
||||
}
|
||||
|
||||
class EmuThread final {
|
||||
bool started = false;
|
||||
|
||||
public:
|
||||
explicit EmuThread() noexcept;
|
||||
~EmuThread() = default;
|
||||
void run() const noexcept;
|
||||
void TogglePause() const noexcept;
|
||||
void Reset() const noexcept;
|
||||
void Stop() const noexcept;
|
||||
|
||||
bool interruptionRequested = false, parallelRDPInitialized = false;
|
||||
};
|
||||
+108
-8
@@ -1,32 +1,95 @@
|
||||
#include <KaizenGui.hpp>
|
||||
#include <backend/Core.hpp>
|
||||
#include <QMenuBar>
|
||||
#include <QMenu>
|
||||
#include <QMessageBox>
|
||||
#include <QCoreApplication>
|
||||
#include <QStatusBar>
|
||||
#include <QTimer>
|
||||
#include <resources/gamecontrollerdb.h>
|
||||
#include <Options.hpp>
|
||||
#include <Scheduler.hpp>
|
||||
|
||||
KaizenGui::KaizenGui() noexcept {
|
||||
KaizenGui::KaizenGui() noexcept : settings(QSettings::UserScope) {
|
||||
SDL_InitSubSystem(SDL_INIT_GAMEPAD);
|
||||
|
||||
hide();
|
||||
vulkanWidget = new RenderWidget();
|
||||
|
||||
cpuTypeLabel = new QLabel("Interpreter");
|
||||
if (Options::GetCpuType() == 1)
|
||||
cpuTypeLabel->setText("Cached Interpreter");
|
||||
|
||||
fpsLabel = new QLabel("Not running");
|
||||
|
||||
statusBar()->addWidget(fpsLabel);
|
||||
statusBar()->addWidget(cpuTypeLabel);
|
||||
|
||||
setWindowTitle("Kaizen " KAIZEN_VERSION_STR);
|
||||
setMinimumSize(640, 480);
|
||||
setCentralWidget(vulkanWidget);
|
||||
|
||||
statusBarTimer = new QTimer();
|
||||
|
||||
connect(statusBarTimer, &QTimer::timeout, this, [&] {
|
||||
pause->setText("Pause");
|
||||
fpsLabel->setText(std::format("FPS: {:.2f}", 1000.f / elapsed).c_str());
|
||||
if (core.pause) {
|
||||
pause->setText("Resume");
|
||||
fpsLabel->setText("Paused");
|
||||
}
|
||||
|
||||
if (!core.romLoaded) {
|
||||
pause->setDisabled(true);
|
||||
reset->setDisabled(true);
|
||||
stop->setDisabled(true);
|
||||
fpsLabel->setText("Not running");
|
||||
}
|
||||
});
|
||||
|
||||
statusBarTimer->start();
|
||||
|
||||
auto fileMenu = menuBar()->addMenu("File");
|
||||
auto open = fileMenu->addAction("Open");
|
||||
connect(open, &QAction::triggered, this, [&] {
|
||||
auto fileToLoad =
|
||||
QFileDialog::getOpenFileName(this, "Select a Nintendo 64 ROM", QDir::currentPath(),
|
||||
"N64 ROM (*.z64 *.n64 *.v64)", nullptr, QFileDialog::DontUseNativeDialog)
|
||||
.toStdString();
|
||||
if (!fileToLoad.empty())
|
||||
LoadROM(fileToLoad);
|
||||
});
|
||||
|
||||
auto exit = fileMenu->addAction("Exit");
|
||||
auto emulationMenu = menuBar()->addMenu("Emulation");
|
||||
auto settingsMenu = emulationMenu->addAction("Settings");
|
||||
settingsWindow = new SettingsWindow();
|
||||
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
|
||||
|
||||
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
|
||||
cpuTypeLabel->setText("Cached Interpreter");
|
||||
if (Options::GetCpuType() == 0)
|
||||
cpuTypeLabel->setText("Interpreter");
|
||||
});
|
||||
|
||||
emulationMenu->addSeparator();
|
||||
auto pause = emulationMenu->addAction("Pause");
|
||||
auto reset = emulationMenu->addAction("Reset");
|
||||
auto stop = emulationMenu->addAction("Stop");
|
||||
|
||||
pause->setDisabled(true);
|
||||
emulationMenu->addAction(pause);
|
||||
connect(pause, &QAction::triggered, this, [&] {
|
||||
if (!core.pause)
|
||||
Scheduler::GetInstance().EnqueueRelative(0, PAUSE);
|
||||
else
|
||||
core.TogglePause();
|
||||
});
|
||||
|
||||
reset->setDisabled(true);
|
||||
emulationMenu->addAction(reset);
|
||||
connect(reset, &QAction::triggered, this, [&] { Scheduler::GetInstance().EnqueueRelative(0, RESET); });
|
||||
|
||||
stop->setDisabled(true);
|
||||
emulationMenu->addAction(stop);
|
||||
connect(stop, &QAction::triggered, this, [&] { Scheduler::GetInstance().EnqueueRelative(0, STOP); });
|
||||
|
||||
auto helpMenu = menuBar()->addMenu("Help");
|
||||
auto about = helpMenu->addAction("About");
|
||||
connect(about, &QAction::triggered, this, [&] {
|
||||
@@ -39,16 +102,53 @@ KaizenGui::KaizenGui() noexcept {
|
||||
|
||||
QMessageBox::about(this, "About", text.c_str());
|
||||
});
|
||||
|
||||
restoreGeometry(settings.value("geometry").toByteArray());
|
||||
restoreState(settings.value("windowState").toByteArray());
|
||||
|
||||
show();
|
||||
|
||||
emuThread = QThread::create([&] {
|
||||
core.parallel.Init(vulkanWidget->wsiPlatform, vulkanWidget->windowInfo, vulkanWidget->qtVkInstanceFactory.get(),
|
||||
core.GetMem().GetRDRAMPtr());
|
||||
while (!emuThread->isInterruptionRequested()) {
|
||||
if (!core.romLoaded) {
|
||||
core.parallel.UpdateScreen<false>();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!core.pause) {
|
||||
auto timeStart = SDL_GetTicks();
|
||||
core.Run();
|
||||
core.parallel.UpdateScreen<true>();
|
||||
elapsed = SDL_GetTicks() - timeStart;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
emuThread->start();
|
||||
}
|
||||
|
||||
KaizenGui::~KaizenGui() { SDL_Quit(); }
|
||||
KaizenGui::~KaizenGui() {
|
||||
SDL_Quit();
|
||||
emuThread->requestInterruption();
|
||||
emuThread->quit();
|
||||
}
|
||||
|
||||
void KaizenGui::LoadROM(const std::string &path) noexcept {
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
core.LoadROM(path);
|
||||
const auto gameNameDB = n64::Core::GetMem().rom.gameNameDB;
|
||||
setWindowTitle(("Kaizen " KAIZEN_VERSION_STR " - " + gameNameDB).c_str());
|
||||
pause->setEnabled(true);
|
||||
reset->setEnabled(true);
|
||||
stop->setEnabled(true);
|
||||
setWindowTitle(("Kaizen " KAIZEN_VERSION_STR " - " + n64::Core::GetMem().rom.gameNameDB).c_str());
|
||||
}
|
||||
|
||||
void KaizenGui::LoadTAS(const std::string &path) noexcept { n64::Core::GetInstance().LoadTAS(fs::path(path)); }
|
||||
|
||||
void KaizenGui::closeEvent(QCloseEvent *event) {
|
||||
settings.setValue("geometry", saveGeometry());
|
||||
settings.setValue("windowState", saveState());
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
+21
-13
@@ -1,41 +1,49 @@
|
||||
#pragma once
|
||||
#include <RenderWidget.hpp>
|
||||
#include <EmuThread.hpp>
|
||||
#include <SettingsWindow.hpp>
|
||||
#include <SDL3/SDL_gamepad.h>
|
||||
#include <QMainWindow>
|
||||
#include <QFileDialog>
|
||||
#include <Core.hpp>
|
||||
|
||||
class EmuThread;
|
||||
|
||||
class KaizenGui final : QMainWindow {
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit KaizenGui() noexcept;
|
||||
~KaizenGui();
|
||||
|
||||
void closeEvent(QCloseEvent *) override;
|
||||
|
||||
bool fastForward = false;
|
||||
bool unlockFramerate = false;
|
||||
bool minimized = false;
|
||||
|
||||
SettingsWindow *settingsWindow;
|
||||
RenderWidget *vulkanWidget;
|
||||
EmuThread emuThread;
|
||||
QSettings settings;
|
||||
QThread *emuThread;
|
||||
QThread *fileWorker;
|
||||
QTimer *statusBarTimer;
|
||||
QLabel *fpsLabel;
|
||||
QLabel *cpuTypeLabel;
|
||||
QAction *pause = new QAction("Pause");
|
||||
QAction *reset = new QAction("Reset");
|
||||
QAction *stop = new QAction("Stop");
|
||||
|
||||
SDL_Gamepad *gamepad = nullptr;
|
||||
|
||||
static void LoadTAS(const std::string &path) noexcept;
|
||||
void LoadROM(const std::string &path) noexcept;
|
||||
signals:
|
||||
void paused();
|
||||
|
||||
private:
|
||||
float elapsed = 0.f;
|
||||
int width{}, height{};
|
||||
bool aboutOpen = false;
|
||||
bool fileDialogOpen = false;
|
||||
bool quit = false;
|
||||
bool shouldDisplaySpinner = false;
|
||||
std::string fileToLoad = "";
|
||||
|
||||
void FileWorker() {
|
||||
if (fileToLoad.empty())
|
||||
return;
|
||||
|
||||
LoadROM(fileToLoad);
|
||||
shouldDisplaySpinner = false;
|
||||
fileToLoad = "";
|
||||
}
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
};
|
||||
|
||||
@@ -44,6 +44,4 @@ RenderWidget::RenderWidget() {
|
||||
|
||||
wsiPlatform = std::make_shared<QtWSIPlatform>(windowHandle());
|
||||
windowInfo = std::make_shared<QtPrdpWindowInfo>(windowHandle());
|
||||
n64::Core &core = n64::Core::GetInstance();
|
||||
core.parallel.Init(wsiPlatform, windowInfo, qtVkInstanceFactory.get(), core.GetMem().GetRDRAMPtr());
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include <ParallelRDPWrapper.hpp>
|
||||
#include <QVulkanWindow>
|
||||
#include <QMainWindow>
|
||||
#include <QThread>
|
||||
|
||||
struct InputSettings;
|
||||
|
||||
@@ -34,11 +35,14 @@ struct QtInstanceFactory : Vulkan::InstanceFactory {
|
||||
};
|
||||
|
||||
class RenderWidget final : public QWidget {
|
||||
Q_OBJECT
|
||||
QVulkanInstance inst;
|
||||
|
||||
public:
|
||||
explicit RenderWidget();
|
||||
|
||||
QPaintEngine *paintEngine() const override { return nullptr; }
|
||||
|
||||
std::unique_ptr<QtInstanceFactory> qtVkInstanceFactory;
|
||||
std::shared_ptr<ParallelRDP::WindowInfo> windowInfo;
|
||||
std::shared_ptr<QtWSIPlatform> wsiPlatform;
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
#include <AudioSettings.hpp>
|
||||
#include <Options.hpp>
|
||||
#include <QSettings>
|
||||
|
||||
AudioSettings::AudioSettings() {
|
||||
volume = new QSlider();
|
||||
AudioSettings::AudioSettings() : settings(QSettings::UserScope) {
|
||||
volumePercent = new QLabel();
|
||||
volumePercent->setText(std::format("Volume: {:.2f}%", Options::GetVolume() * 100.f).c_str());
|
||||
volume = new QSlider(Qt::Horizontal);
|
||||
volume->setRange(0, 100);
|
||||
volume->setValue(int(Options::GetVolume()) * 100.f);
|
||||
QSettings settings;
|
||||
volume->setValue(Options::GetVolume() * 100.f);
|
||||
connect(volume, &QSlider::valueChanged, this, [&] {
|
||||
float newValue = float(volume->value()) / 100.f;
|
||||
volumePercent->setText(std::format("Volume: {:.2f}%", Options::GetVolume() * 100.f).c_str());
|
||||
Options::SetVolume(newValue);
|
||||
settings.setValue("audio/volume", newValue);
|
||||
settings.sync();
|
||||
});
|
||||
|
||||
v = new QVBoxLayout();
|
||||
v->addWidget(volume);
|
||||
v->addWidget(volumePercent);
|
||||
setLayout(v);
|
||||
}
|
||||
|
||||
@@ -2,10 +2,15 @@
|
||||
#include <QWidget>
|
||||
#include <QVBoxLayout>
|
||||
#include <QSlider>
|
||||
#include <QSettings>
|
||||
#include <QLabel>
|
||||
|
||||
class AudioSettings final : public QWidget {
|
||||
Q_OBJECT
|
||||
QVBoxLayout *v;
|
||||
QSlider *volume;
|
||||
QLabel *volumePercent;
|
||||
QSettings settings;
|
||||
|
||||
public:
|
||||
explicit AudioSettings();
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#include <CPUSettings.hpp>
|
||||
#include <Options.hpp>
|
||||
#include <log.hpp>
|
||||
#include <QSettings>
|
||||
|
||||
CPUSettings::CPUSettings() {
|
||||
CPUSettings::CPUSettings() : settings(QSettings::UserScope) {
|
||||
types = new QComboBox();
|
||||
idleSkip = new QCheckBox("Idle skipping");
|
||||
idleSkip->setToolTip("Whether to enable idle skipping.<br><br>"
|
||||
@@ -11,36 +10,41 @@ CPUSettings::CPUSettings() {
|
||||
"that enables skipping the execution of certain blocks of guest code<br>"
|
||||
"when it's determined that the aforementioned is used to wait on a certain<br>"
|
||||
"event to occur; the code gets skipped, the event is executed immediately by<br>"
|
||||
"the emulator so that the game never actually waits, progressing immediately<br>"
|
||||
"and making emulation much faster.<br><br>"
|
||||
"the emulator so that the game never actually waits, progressing immediately and making "
|
||||
"emulation much faster.<br><br>"
|
||||
"This feature is not available when the pure interpreter is selected<br>"
|
||||
"because the information regarding instructions would be too limited to perform<br>"
|
||||
"the evaluation above described.");
|
||||
"because the information regarding instructions would be too limited to<br>"
|
||||
"perform the evaluation described above.");
|
||||
|
||||
idleSkip->setChecked(settings.value("cpu/idle_skip", false).value<bool>());
|
||||
v = new QVBoxLayout();
|
||||
h = new QHBoxLayout();
|
||||
|
||||
types->addItems({"Interpreter", "Cached Interpreter"});
|
||||
if (Options::GetCpuType() == 0) {
|
||||
idleSkip->hide();
|
||||
} else {
|
||||
idleSkip->show();
|
||||
}
|
||||
types->setCurrentIndex(Options::GetCpuType());
|
||||
|
||||
QSettings settings;
|
||||
connect(types, &QComboBox::currentIndexChanged, this, [&] {
|
||||
int index = types->currentIndex();
|
||||
QString newValue{};
|
||||
if (index == 0) {
|
||||
if (index == 0)
|
||||
idleSkip->hide();
|
||||
newValue = "interpreter";
|
||||
}
|
||||
if (index == 1) {
|
||||
else
|
||||
idleSkip->show();
|
||||
newValue = "cached_interpreter";
|
||||
}
|
||||
|
||||
Options::SetCpuType(newValue.toStdString());
|
||||
settings.setValue("cpu/type", newValue);
|
||||
Options::SetCpuType(index);
|
||||
settings.setValue("cpu/type", index);
|
||||
settings.sync();
|
||||
emit cpuTypeChanged();
|
||||
});
|
||||
|
||||
connect(idleSkip, &QCheckBox::checkStateChanged, this, [&] {
|
||||
Options::SetIdleSkip(idleSkip->checkState());
|
||||
settings.setValue("cpu/idle_skip", idleSkip->checkState());
|
||||
settings.sync();
|
||||
});
|
||||
|
||||
h->addWidget(idleSkip);
|
||||
|
||||
@@ -4,13 +4,18 @@
|
||||
#include <QCheckBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QSettings>
|
||||
|
||||
class CPUSettings final : public QWidget {
|
||||
Q_OBJECT
|
||||
QComboBox *types;
|
||||
QCheckBox *idleSkip;
|
||||
QVBoxLayout *v;
|
||||
QHBoxLayout *h;
|
||||
QSettings settings;
|
||||
|
||||
public:
|
||||
explicit CPUSettings();
|
||||
signals:
|
||||
void cpuTypeChanged();
|
||||
};
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
#include <GeneralSettings.hpp>
|
||||
#include <Options.hpp>
|
||||
#include <QSettings>
|
||||
#include <QFileDialog>
|
||||
#include <QCoreApplication>
|
||||
#include <log.hpp>
|
||||
|
||||
GeneralSettings::GeneralSettings() {
|
||||
QSettings settings;
|
||||
GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
|
||||
description = new QLabel("Path:");
|
||||
description->setToolTip("Path where game saves are stored.");
|
||||
selectedFolderLabel = new QLabel(Options::GetSavesPath().c_str());
|
||||
@@ -15,10 +13,12 @@ GeneralSettings::GeneralSettings() {
|
||||
|
||||
connect(folderSelectButton, &QPushButton::clicked, this, [&] {
|
||||
auto dir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), QCoreApplication::applicationDirPath(),
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
||||
QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks |
|
||||
QFileDialog::DontUseNativeDialog);
|
||||
selectedFolderLabel->setText(dir);
|
||||
Options::SetSavesPath(dir.toStdString());
|
||||
settings.setValue("general/savesPath", dir);
|
||||
settings.setValue("general/saves_path", dir);
|
||||
settings.sync();
|
||||
});
|
||||
|
||||
h = new QHBoxLayout();
|
||||
|
||||
@@ -3,13 +3,16 @@
|
||||
#include <QPushButton>
|
||||
#include <QVBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QSettings>
|
||||
|
||||
class GeneralSettings final : public QWidget {
|
||||
Q_OBJECT
|
||||
QLabel *description;
|
||||
QPushButton *folderSelectButton;
|
||||
QLabel *selectedFolderLabel;
|
||||
QVBoxLayout *v;
|
||||
QHBoxLayout *h;
|
||||
QSettings settings;
|
||||
|
||||
public:
|
||||
explicit GeneralSettings();
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <CPUSettings.hpp>
|
||||
|
||||
class SettingsWindow final : public QWidget {
|
||||
Q_OBJECT
|
||||
QTabWidget *categories;
|
||||
GeneralSettings *general;
|
||||
AudioSettings *audio;
|
||||
@@ -15,5 +16,6 @@ class SettingsWindow final : public QWidget {
|
||||
QVBoxLayout *v;
|
||||
|
||||
public:
|
||||
friend class KaizenGui;
|
||||
SettingsWindow();
|
||||
};
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
#include <QSettings>
|
||||
|
||||
Options::Options() {
|
||||
QSettings settings;
|
||||
QSettings settings(QSettings::UserScope);
|
||||
volume = settings.value("audio/volume", 0.5f).toFloat();
|
||||
cpuType = settings.value("cpu/type", "interpreter").toString().toStdString();
|
||||
cpuType = settings.value("cpu/type", 0).toUInt();
|
||||
idleSkip = settings.value("cpu/idle_skip", false).toBool();
|
||||
savesPath = settings.value("general/saves_path", "saves").toString().toStdString();
|
||||
}
|
||||
|
||||
@@ -12,16 +12,16 @@ struct Options {
|
||||
|
||||
static bool GetIdleSkip() { return GetInstance().idleSkip; }
|
||||
static float GetVolume() { return GetInstance().volume; }
|
||||
static std::string GetCpuType() { return GetInstance().cpuType; }
|
||||
static uint8_t GetCpuType() { return GetInstance().cpuType; }
|
||||
static std::string GetSavesPath() { return GetInstance().savesPath; }
|
||||
static void SetIdleSkip(bool v) { GetInstance().idleSkip = v; }
|
||||
static void SetVolume(float v) { GetInstance().volume = v; }
|
||||
static void SetCpuType(const std::string &v) { GetInstance().cpuType = v; }
|
||||
static void SetCpuType(uint8_t v) { GetInstance().cpuType = v; }
|
||||
static void SetSavesPath(const std::string &v) { GetInstance().savesPath = v; }
|
||||
|
||||
private:
|
||||
bool idleSkip = false;
|
||||
float volume = 0.5;
|
||||
std::string savesPath = "saves";
|
||||
std::string cpuType = "interpreter";
|
||||
uint8_t cpuType = 0;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user