input
This commit is contained in:
@@ -139,6 +139,7 @@ if (${CMAKE_BUILD_TYPE} MATCHES Debug AND VULKAN_VALIDATION)
|
|||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)
|
||||||
|
qt_standard_project_setup()
|
||||||
|
|
||||||
add_subdirectory(external/mio)
|
add_subdirectory(external/mio)
|
||||||
add_subdirectory(src/backend)
|
add_subdirectory(src/backend)
|
||||||
@@ -184,6 +185,19 @@ if (SANITIZERS)
|
|||||||
target_link_options(kaizen PUBLIC -fsanitize=undefined -fsanitize=address)
|
target_link_options(kaizen PUBLIC -fsanitize=undefined -fsanitize=address)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
install(TARGETS kaizen
|
||||||
|
BUNDLE DESTINATION .
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
qt_generate_deploy_app_script(
|
||||||
|
TARGET kaizen
|
||||||
|
OUTPUT_SCRIPT deploy_script
|
||||||
|
NO_UNSUPPORTED_PLATFORM_ERROR
|
||||||
|
)
|
||||||
|
|
||||||
|
install(SCRIPT ${deploy_script})
|
||||||
|
|
||||||
file(COPY resources/ DESTINATION ${PROJECT_BINARY_DIR}/resources/)
|
file(COPY resources/ DESTINATION ${PROJECT_BINARY_DIR}/resources/)
|
||||||
file(REMOVE
|
file(REMOVE
|
||||||
${PROJECT_BINARY_DIR}/resources/mario.png
|
${PROJECT_BINARY_DIR}/resources/mario.png
|
||||||
|
|||||||
+1
-7
@@ -194,8 +194,7 @@ void ParallelRDP::UpdateScreen(Util::IntrusivePtr<Image> image) const {
|
|||||||
wsi->end_frame();
|
wsi->end_frame();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
void ParallelRDP::UpdateScreen() const {
|
||||||
void ParallelRDP::UpdateScreen<true>() const {
|
|
||||||
const n64::VI &vi = n64::Core::GetMem().mmio.vi;
|
const n64::VI &vi = n64::Core::GetMem().mmio.vi;
|
||||||
command_processor->set_vi_register(VIRegister::Control, vi.status.raw);
|
command_processor->set_vi_register(VIRegister::Control, vi.status.raw);
|
||||||
command_processor->set_vi_register(VIRegister::Origin, vi.origin);
|
command_processor->set_vi_register(VIRegister::Origin, vi.origin);
|
||||||
@@ -225,11 +224,6 @@ void ParallelRDP::UpdateScreen<true>() const {
|
|||||||
command_processor->begin_frame_context();
|
command_processor->begin_frame_context();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <>
|
|
||||||
void ParallelRDP::UpdateScreen<false>() const {
|
|
||||||
UpdateScreen(static_cast<Util::IntrusivePtr<Image>>(nullptr));
|
|
||||||
}
|
|
||||||
|
|
||||||
void ParallelRDP::EnqueueCommand(const int command_length, const u32 *buffer) const {
|
void ParallelRDP::EnqueueCommand(const int command_length, const u32 *buffer) const {
|
||||||
command_processor->enqueue_command(command_length, buffer);
|
command_processor->enqueue_command(command_length, buffer);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ class ParallelRDP {
|
|||||||
void Init(const std::shared_ptr<Vulkan::WSIPlatform> &, const std::shared_ptr<WindowInfo> &,
|
void Init(const std::shared_ptr<Vulkan::WSIPlatform> &, const std::shared_ptr<WindowInfo> &,
|
||||||
Vulkan::InstanceFactory *, const u8 *);
|
Vulkan::InstanceFactory *, const u8 *);
|
||||||
|
|
||||||
template <bool>
|
|
||||||
void UpdateScreen() const;
|
void UpdateScreen() const;
|
||||||
void EnqueueCommand(int, const u32 *) const;
|
void EnqueueCommand(int, const u32 *) const;
|
||||||
void OnFullSync() const;
|
void OnFullSync() const;
|
||||||
|
|||||||
+1
-10
@@ -4,16 +4,7 @@
|
|||||||
#include <Options.hpp>
|
#include <Options.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
Core::Core() : interpreter(*mem, regs) {
|
Core::Core() : interpreter(*mem, regs) { cpuType = Options::GetCpuType(); }
|
||||||
const auto selectedCpu = Options::GetCpuType();
|
|
||||||
if (selectedCpu == 0) {
|
|
||||||
cpuType = PlainInterpreter;
|
|
||||||
} else if (selectedCpu == 1) {
|
|
||||||
cpuType = CachedInterpreter;
|
|
||||||
} else {
|
|
||||||
panic("Unimplemented CPU type");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void Core::Stop() {
|
void Core::Stop() {
|
||||||
pause = true;
|
pause = true;
|
||||||
|
|||||||
@@ -4,12 +4,10 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <Registers.hpp>
|
#include <Registers.hpp>
|
||||||
|
#include <Options.hpp>
|
||||||
|
|
||||||
namespace n64 {
|
namespace n64 {
|
||||||
struct Core {
|
struct Core {
|
||||||
enum CPUType { PlainInterpreter, CachedInterpreter } cpuType = CachedInterpreter;
|
|
||||||
|
|
||||||
bool idleSkip = true;
|
|
||||||
explicit Core();
|
explicit Core();
|
||||||
|
|
||||||
static Core &GetInstance() {
|
static Core &GetInstance() {
|
||||||
@@ -43,10 +41,12 @@ struct Core {
|
|||||||
breakpoints.insert(addr);
|
breakpoints.insert(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool idleSkip = true;
|
||||||
bool pause = true;
|
bool pause = true;
|
||||||
bool romLoaded = false;
|
bool romLoaded = false;
|
||||||
int slot = 0;
|
int slot = 0;
|
||||||
size_t memSize{}, cpuSize{}, verSize{};
|
size_t memSize{}, cpuSize{}, verSize{};
|
||||||
|
CPUType cpuType;
|
||||||
std::string rom;
|
std::string rom;
|
||||||
std::set<s64> breakpoints{};
|
std::set<s64> breakpoints{};
|
||||||
std::unique_ptr<Mem> mem = std::make_unique<Mem>();
|
std::unique_ptr<Mem> mem = std::make_unique<Mem>();
|
||||||
|
|||||||
+88
-27
@@ -22,11 +22,11 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
vulkanWidget->hide();
|
vulkanWidget->hide();
|
||||||
|
|
||||||
cpuTypeLabel = new QLabel("Interpreter");
|
cpuTypeLabel = new QLabel("Interpreter");
|
||||||
if (Options::GetCpuType() == 1)
|
if (Options::GetCpuType() == n64::CachedInterpreter)
|
||||||
cpuTypeLabel->setText("Cached Interpreter");
|
cpuTypeLabel->setText("Cached Interpreter");
|
||||||
|
|
||||||
idleSkipLabel = new QLabel("Idle skipping");
|
idleSkipLabel = new QLabel("Idle skipping");
|
||||||
if (!Options::GetIdleSkip())
|
if (!Options::GetIdleSkip() || Options::GetCpuType() == n64::PlainInterpreter)
|
||||||
idleSkipLabel->hide();
|
idleSkipLabel->hide();
|
||||||
|
|
||||||
fpsLabel = new QLabel("Not running");
|
fpsLabel = new QLabel("Not running");
|
||||||
@@ -42,7 +42,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
statusBarTimer = new QTimer();
|
statusBarTimer = new QTimer();
|
||||||
statusBarTimer->setInterval(1000);
|
statusBarTimer->setInterval(500);
|
||||||
|
|
||||||
connect(statusBarTimer, &QTimer::timeout, this, [&] {
|
connect(statusBarTimer, &QTimer::timeout, this, [&] {
|
||||||
pause->setText("Pause");
|
pause->setText("Pause");
|
||||||
@@ -53,6 +53,7 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!core.romLoaded) {
|
if (!core.romLoaded) {
|
||||||
|
pause->setText("Pause");
|
||||||
pause->setDisabled(true);
|
pause->setDisabled(true);
|
||||||
reset->setDisabled(true);
|
reset->setDisabled(true);
|
||||||
stop->setDisabled(true);
|
stop->setDisabled(true);
|
||||||
@@ -64,10 +65,10 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
|
|
||||||
auto fileMenu = menuBar()->addMenu("File");
|
auto fileMenu = menuBar()->addMenu("File");
|
||||||
auto open = fileMenu->addAction("Open");
|
auto open = fileMenu->addAction("Open");
|
||||||
|
open->setShortcut(QKeyCombination(Qt::CTRL, Qt::Key_O));
|
||||||
connect(open, &QAction::triggered, this, [&] {
|
connect(open, &QAction::triggered, this, [&] {
|
||||||
auto fileToLoad =
|
auto fileToLoad = QFileDialog::getOpenFileName(this, "Select a Nintendo 64 ROM", QDir::currentPath(),
|
||||||
QFileDialog::getOpenFileName(this, "Select a Nintendo 64 ROM", QDir::currentPath(),
|
"N64 ROM (*.z64 *.n64 *.v64)")
|
||||||
"N64 ROM (*.z64 *.n64 *.v64)", nullptr, QFileDialog::DontUseNativeDialog)
|
|
||||||
.toStdString();
|
.toStdString();
|
||||||
if (!fileToLoad.empty())
|
if (!fileToLoad.empty())
|
||||||
LoadROM(fileToLoad);
|
LoadROM(fileToLoad);
|
||||||
@@ -82,20 +83,28 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
|
connect(settingsMenu, &QAction::triggered, settingsWindow, &SettingsWindow::show);
|
||||||
|
|
||||||
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
|
connect(settingsWindow->cpu, &CPUSettings::cpuTypeChanged, this, [&] {
|
||||||
|
core.cpuType = Options::GetCpuType();
|
||||||
cpuTypeLabel->setText("Cached Interpreter");
|
cpuTypeLabel->setText("Cached Interpreter");
|
||||||
if (Options::GetCpuType() == 0)
|
idleSkipLabel->setVisible(Options::GetCpuType() == n64::CachedInterpreter);
|
||||||
|
if (Options::GetCpuType() == n64::PlainInterpreter)
|
||||||
cpuTypeLabel->setText("Interpreter");
|
cpuTypeLabel->setText("Interpreter");
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(settingsWindow->cpu, &CPUSettings::idleSkipChanged, this, [&] {
|
connect(settingsWindow->cpu, &CPUSettings::idleSkipChanged, this, [&] {
|
||||||
idleSkipLabel->show();
|
core.idleSkip = Options::GetIdleSkip();
|
||||||
if (!Options::GetIdleSkip())
|
idleSkipLabel->setVisible(Options::GetIdleSkip());
|
||||||
idleSkipLabel->hide();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
emulationMenu->addSeparator();
|
emulationMenu->addSeparator();
|
||||||
|
|
||||||
|
auto unlockFramerate = emulationMenu->addAction("Unlock framerate");
|
||||||
|
unlockFramerate->setCheckable(true);
|
||||||
|
|
||||||
|
connect(unlockFramerate, &QAction::triggered, this,
|
||||||
|
[&](bool checked) { core.parallel.SetFramerateUnlocked(checked); });
|
||||||
|
|
||||||
pause->setDisabled(true);
|
pause->setDisabled(true);
|
||||||
|
pause->setShortcut(QKeyCombination(Qt::CTRL, Qt::Key_P));
|
||||||
emulationMenu->addAction(pause);
|
emulationMenu->addAction(pause);
|
||||||
connect(pause, &QAction::triggered, this, [&] {
|
connect(pause, &QAction::triggered, this, [&] {
|
||||||
if (!core.pause)
|
if (!core.pause)
|
||||||
@@ -104,11 +113,14 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
core.TogglePause();
|
core.TogglePause();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
reset->setDisabled(true);
|
reset->setDisabled(true);
|
||||||
|
reset->setShortcut(QKeyCombination(Qt::CTRL, Qt::Key_R));
|
||||||
emulationMenu->addAction(reset);
|
emulationMenu->addAction(reset);
|
||||||
connect(reset, &QAction::triggered, this, [&] { Scheduler::GetInstance().EnqueueRelative(0, RESET); });
|
connect(reset, &QAction::triggered, this, [&] { Scheduler::GetInstance().EnqueueRelative(0, RESET); });
|
||||||
|
|
||||||
stop->setDisabled(true);
|
stop->setDisabled(true);
|
||||||
|
stop->setShortcut(QKeyCombination(Qt::CTRL, Qt::Key_X));
|
||||||
emulationMenu->addAction(stop);
|
emulationMenu->addAction(stop);
|
||||||
connect(stop, &QAction::triggered, this, [&] {
|
connect(stop, &QAction::triggered, this, [&] {
|
||||||
Scheduler::GetInstance().EnqueueRelative(0, STOP);
|
Scheduler::GetInstance().EnqueueRelative(0, STOP);
|
||||||
@@ -134,47 +146,82 @@ KaizenGui::KaizenGui() noexcept : QMainWindow(nullptr), settings(QSettings::User
|
|||||||
core.parallel.Init(vulkanWidget->wsiPlatform, vulkanWidget->windowInfo, vulkanWidget->qtVkInstanceFactory.get(),
|
core.parallel.Init(vulkanWidget->wsiPlatform, vulkanWidget->windowInfo, vulkanWidget->qtVkInstanceFactory.get(),
|
||||||
core.GetMem().GetRDRAMPtr());
|
core.GetMem().GetRDRAMPtr());
|
||||||
while (!emuThread->isInterruptionRequested()) {
|
while (!emuThread->isInterruptionRequested()) {
|
||||||
if (!core.romLoaded) {
|
if (!core.romLoaded || core.pause)
|
||||||
core.parallel.UpdateScreen<false>();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
|
||||||
|
|
||||||
if (!core.pause) {
|
updateKeys();
|
||||||
|
updateAxis();
|
||||||
|
|
||||||
auto timeStart = SDL_GetTicks();
|
auto timeStart = SDL_GetTicks();
|
||||||
core.Run();
|
core.Run();
|
||||||
core.parallel.UpdateScreen<true>();
|
core.parallel.UpdateScreen();
|
||||||
elapsed = SDL_GetTicks() - timeStart;
|
elapsed = SDL_GetTicks() - timeStart;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
emuThread->start();
|
emuThread->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
KaizenGui::~KaizenGui() {
|
KaizenGui::~KaizenGui() { cleanup(); }
|
||||||
SDL_Quit();
|
|
||||||
emuThread->requestInterruption();
|
void KaizenGui::updateKeys() {
|
||||||
emuThread->quit();
|
auto &pif = core.mem->mmio.si.pif;
|
||||||
|
pif.UpdateButton(0, n64::Controller::Z, pressedKeys.test(0));
|
||||||
|
pif.UpdateButton(0, n64::Controller::A, pressedKeys.test(1));
|
||||||
|
pif.UpdateButton(0, n64::Controller::B, pressedKeys.test(2));
|
||||||
|
pif.UpdateButton(0, n64::Controller::LT, pressedKeys.test(3));
|
||||||
|
pif.UpdateButton(0, n64::Controller::RT, pressedKeys.test(4));
|
||||||
|
pif.UpdateButton(0, n64::Controller::Start, pressedKeys.test(5));
|
||||||
|
pif.UpdateButton(0, n64::Controller::DUp, pressedKeys.test(6));
|
||||||
|
pif.UpdateButton(0, n64::Controller::DDown, pressedKeys.test(7));
|
||||||
|
pif.UpdateButton(0, n64::Controller::DLeft, pressedKeys.test(8));
|
||||||
|
pif.UpdateButton(0, n64::Controller::DRight, pressedKeys.test(9));
|
||||||
|
pif.UpdateButton(0, n64::Controller::CUp, pressedKeys.test(10));
|
||||||
|
pif.UpdateButton(0, n64::Controller::CDown, pressedKeys.test(11));
|
||||||
|
pif.UpdateButton(0, n64::Controller::CLeft, pressedKeys.test(12));
|
||||||
|
pif.UpdateButton(0, n64::Controller::CRight, pressedKeys.test(13));
|
||||||
|
}
|
||||||
|
|
||||||
|
void KaizenGui::updateAxis() {
|
||||||
|
s16 x = 0, y = 0;
|
||||||
|
auto &pif = core.mem->mmio.si.pif;
|
||||||
|
if (pressedKeys.test(14)) // up
|
||||||
|
y += 86;
|
||||||
|
|
||||||
|
if (pressedKeys.test(15)) // down
|
||||||
|
y -= 86;
|
||||||
|
|
||||||
|
if (pressedKeys.test(16)) // left
|
||||||
|
x -= 86;
|
||||||
|
|
||||||
|
if (pressedKeys.test(17)) // right
|
||||||
|
x += 86;
|
||||||
|
|
||||||
|
core.mem->mmio.si.pif.UpdateAxis(0, n64::Controller::X, x);
|
||||||
|
core.mem->mmio.si.pif.UpdateAxis(0, n64::Controller::Y, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void KaizenGui::LoadROM(const std::string &path) noexcept {
|
void KaizenGui::LoadROM(const std::string &path) noexcept {
|
||||||
n64::Core &core = n64::Core::GetInstance();
|
|
||||||
core.LoadROM(path);
|
core.LoadROM(path);
|
||||||
pause->setEnabled(true);
|
pause->setEnabled(true);
|
||||||
reset->setEnabled(true);
|
reset->setEnabled(true);
|
||||||
stop->setEnabled(true);
|
stop->setEnabled(true);
|
||||||
vulkanWidget->show();
|
vulkanWidget->show();
|
||||||
setWindowTitle(("Kaizen " KAIZEN_VERSION_STR " - " + n64::Core::GetMem().rom.gameNameDB).c_str());
|
setWindowTitle(("Kaizen " KAIZEN_VERSION_STR " - " + core.mem->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 { core.LoadTAS(fs::path(path)); }
|
||||||
|
|
||||||
void KaizenGui::closeEvent(QCloseEvent *event) {
|
void KaizenGui::cleanup() {
|
||||||
Scheduler::GetInstance().EnqueueRelative(0, STOP);
|
SDL_Quit();
|
||||||
|
core.Stop();
|
||||||
|
emuThread->requestInterruption();
|
||||||
|
emuThread->quit();
|
||||||
|
delete emuThread;
|
||||||
|
delete vulkanWidget;
|
||||||
|
delete settingsWindow;
|
||||||
settings.setValue("geometry", saveGeometry());
|
settings.setValue("geometry", saveGeometry());
|
||||||
settings.setValue("windowState", saveState());
|
settings.setValue("windowState", saveState());
|
||||||
QMainWindow::closeEvent(event);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KaizenGui::dropEvent(QDropEvent *event) {
|
void KaizenGui::dropEvent(QDropEvent *event) {
|
||||||
@@ -189,3 +236,17 @@ void KaizenGui::dragEnterEvent(QDragEnterEvent *event) {
|
|||||||
if (event->mimeData()->hasUrls())
|
if (event->mimeData()->hasUrls())
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KaizenGui::keyPressEvent(QKeyEvent *event) {
|
||||||
|
for (int i = 0; i < mapping.size(); i++) {
|
||||||
|
if (mapping[i] == event->key())
|
||||||
|
pressedKeys.set(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void KaizenGui::keyReleaseEvent(QKeyEvent *event) {
|
||||||
|
for (int i = 0; i < mapping.size(); i++) {
|
||||||
|
if (mapping[i] == event->key())
|
||||||
|
pressedKeys.reset(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,28 +7,33 @@
|
|||||||
#include <QDropEvent>
|
#include <QDropEvent>
|
||||||
#include <QDragEnterEvent>
|
#include <QDragEnterEvent>
|
||||||
#include <Core.hpp>
|
#include <Core.hpp>
|
||||||
|
#include <bitset>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
class EmuThread;
|
class EmuThread;
|
||||||
|
|
||||||
class KaizenGui final : QMainWindow {
|
class KaizenGui final : QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
void updateKeys();
|
||||||
|
void updateAxis();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
explicit KaizenGui() noexcept;
|
explicit KaizenGui() noexcept;
|
||||||
~KaizenGui();
|
~KaizenGui();
|
||||||
|
|
||||||
void closeEvent(QCloseEvent *) override;
|
void cleanup();
|
||||||
void dropEvent(QDropEvent *) override;
|
void dropEvent(QDropEvent *) override;
|
||||||
void dragEnterEvent(QDragEnterEvent *) override;
|
void dragEnterEvent(QDragEnterEvent *) override;
|
||||||
|
void keyPressEvent(QKeyEvent *) override;
|
||||||
|
void keyReleaseEvent(QKeyEvent *) override;
|
||||||
|
|
||||||
bool fastForward = false;
|
bool fastForward = false;
|
||||||
bool unlockFramerate = false;
|
|
||||||
bool minimized = false;
|
bool minimized = false;
|
||||||
|
|
||||||
SettingsWindow *settingsWindow;
|
SettingsWindow *settingsWindow;
|
||||||
RenderWidget *vulkanWidget;
|
RenderWidget *vulkanWidget;
|
||||||
QSettings settings;
|
QSettings settings;
|
||||||
QThread *emuThread;
|
QThread *emuThread;
|
||||||
QThread *fileWorker;
|
|
||||||
QTimer *statusBarTimer;
|
QTimer *statusBarTimer;
|
||||||
QLabel *fpsLabel;
|
QLabel *fpsLabel;
|
||||||
QLabel *cpuTypeLabel;
|
QLabel *cpuTypeLabel;
|
||||||
@@ -39,16 +44,18 @@ class KaizenGui final : QMainWindow {
|
|||||||
|
|
||||||
SDL_Gamepad *gamepad = nullptr;
|
SDL_Gamepad *gamepad = nullptr;
|
||||||
|
|
||||||
static 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:
|
signals:
|
||||||
void paused();
|
void paused();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
float elapsed = 0.f;
|
float elapsed = 0.f;
|
||||||
int width{}, height{};
|
|
||||||
bool aboutOpen = false;
|
|
||||||
bool fileDialogOpen = false;
|
|
||||||
bool quit = false;
|
|
||||||
n64::Core &core = n64::Core::GetInstance();
|
n64::Core &core = n64::Core::GetInstance();
|
||||||
|
std::bitset<18> pressedKeys{};
|
||||||
|
std::array<Qt::Key, 18> mapping = {
|
||||||
|
Qt::Key_Z, Qt::Key_X, Qt::Key_C, Qt::Key_A, Qt::Key_S, Qt::Key_Return,
|
||||||
|
Qt::Key_I, Qt::Key_K, Qt::Key_J, Qt::Key_L, Qt::Key_T, Qt::Key_G,
|
||||||
|
Qt::Key_F, Qt::Key_H, Qt::Key_Up, Qt::Key_Down, Qt::Key_Left, Qt::Key_Right,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -21,12 +21,12 @@ CPUSettings::CPUSettings() : settings(QSettings::UserScope) {
|
|||||||
h = new QHBoxLayout();
|
h = new QHBoxLayout();
|
||||||
|
|
||||||
types->addItems({"Interpreter", "Cached Interpreter"});
|
types->addItems({"Interpreter", "Cached Interpreter"});
|
||||||
if (Options::GetCpuType() == 0) {
|
if (Options::GetCpuType() == n64::PlainInterpreter) {
|
||||||
idleSkip->hide();
|
idleSkip->hide();
|
||||||
} else {
|
} else {
|
||||||
idleSkip->show();
|
idleSkip->show();
|
||||||
}
|
}
|
||||||
types->setCurrentIndex(Options::GetCpuType());
|
types->setCurrentIndex((int)Options::GetCpuType());
|
||||||
|
|
||||||
connect(types, &QComboBox::currentIndexChanged, this, [&] {
|
connect(types, &QComboBox::currentIndexChanged, this, [&] {
|
||||||
int index = types->currentIndex();
|
int index = types->currentIndex();
|
||||||
@@ -35,8 +35,8 @@ CPUSettings::CPUSettings() : settings(QSettings::UserScope) {
|
|||||||
else
|
else
|
||||||
idleSkip->show();
|
idleSkip->show();
|
||||||
|
|
||||||
Options::SetCpuType(index);
|
Options::SetCpuType((n64::CPUType)index);
|
||||||
settings.setValue("cpu/type", index);
|
settings.setValue("cpu/type", (n64::CPUType)index);
|
||||||
settings.sync();
|
settings.sync();
|
||||||
emit cpuTypeChanged();
|
emit cpuTypeChanged();
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -13,8 +13,7 @@ GeneralSettings::GeneralSettings() : settings(QSettings::UserScope) {
|
|||||||
|
|
||||||
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/saves_path", dir);
|
settings.setValue("general/saves_path", dir);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
Options::Options() {
|
Options::Options() {
|
||||||
QSettings settings(QSettings::UserScope);
|
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", 0).toUInt();
|
cpuType = settings.value("cpu/type", n64::PlainInterpreter).value<n64::CPUType>();
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
#include <common.hpp>
|
#include <common.hpp>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
namespace n64 {
|
||||||
|
enum CPUType { PlainInterpreter, CachedInterpreter };
|
||||||
|
}
|
||||||
|
|
||||||
struct Options {
|
struct Options {
|
||||||
static Options &GetInstance() {
|
static Options &GetInstance() {
|
||||||
static Options instance;
|
static Options instance;
|
||||||
@@ -12,16 +16,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 uint8_t GetCpuType() { return GetInstance().cpuType; }
|
static n64::CPUType 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(uint8_t v) { GetInstance().cpuType = v; }
|
static void SetCpuType(n64::CPUType 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";
|
||||||
uint8_t cpuType = 0;
|
n64::CPUType cpuType = n64::PlainInterpreter;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user