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