From 25d1e4c51f01ca249570bbc830387bc373b18136 Mon Sep 17 00:00:00 2001 From: Simone Date: Thu, 18 Jan 2024 13:13:05 +0100 Subject: [PATCH] UI itself is usable --- src/backend/Core.cpp | 9 ++- src/frontend/CMakeLists.txt | 9 ++- src/frontend/EmuThread.cpp | 11 ++++ src/frontend/EmuThread.hpp | 36 +++++++++++ src/frontend/KaizenQt.cpp | 28 ++++++++ src/frontend/KaizenQt.hpp | 14 ++++ src/frontend/MainWindow.cpp | 54 ++++++++++++++++ src/frontend/MainWindow.hpp | 24 +++++++ src/frontend/main.cpp | 6 ++ src/frontend/mainwindow.ui | 124 ++++++++++++++++++++++++++++++++++++ 10 files changed, 311 insertions(+), 4 deletions(-) create mode 100644 src/frontend/EmuThread.cpp create mode 100644 src/frontend/EmuThread.hpp create mode 100644 src/frontend/KaizenQt.cpp create mode 100644 src/frontend/KaizenQt.hpp create mode 100644 src/frontend/MainWindow.cpp create mode 100644 src/frontend/MainWindow.hpp create mode 100644 src/frontend/mainwindow.ui diff --git a/src/backend/Core.cpp b/src/backend/Core.cpp index fac75828..9a1dada9 100644 --- a/src/backend/Core.cpp +++ b/src/backend/Core.cpp @@ -18,19 +18,21 @@ Core::Core() { if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) { Util::warn("Failed to load game controller DB"); } + + cpu = std::make_unique(); } void Core::Stop() { - cpu->Reset(); - cpu->mem.Reset(); pause = true; romLoaded = false; + cpu->Reset(); + cpu->mem.Reset(); } void Core::LoadROM(const std::string& rom_) { + pause = true; rom = rom_; cpu->Reset(); - pause = false; romLoaded = true; std::string archive_types[] = {".zip",".7z",".rar",".tar"}; @@ -49,6 +51,7 @@ void Core::LoadROM(const std::string& rom_) { cpu->mem.flash.Load(cpu->mem.saveType, rom); cpu->mem.LoadSRAM(cpu->mem.saveType, rom); PIF::ExecutePIF(cpu->mem, cpu->regs); + pause = false; } void Core::Run(float volumeL, float volumeR) { diff --git a/src/frontend/CMakeLists.txt b/src/frontend/CMakeLists.txt index 4ddb8818..4b112510 100644 --- a/src/frontend/CMakeLists.txt +++ b/src/frontend/CMakeLists.txt @@ -50,7 +50,14 @@ set(CMAKE_AUTORCC ON) set(CMAKE_AUTOUIC ON) add_executable(kaizen-qt - main.cpp) + main.cpp + KaizenQt.hpp + KaizenQt.cpp + EmuThread.hpp + EmuThread.cpp + mainwindow.ui + MainWindow.hpp + MainWindow.cpp) target_link_libraries(kaizen-qt PUBLIC Qt6::Core Qt6::Gui Qt6::Widgets SDL2::SDL2 fmt::fmt mio::mio nlohmann_json::nlohmann_json discord-rpc nfd parallel-rdp backend) diff --git a/src/frontend/EmuThread.cpp b/src/frontend/EmuThread.cpp new file mode 100644 index 00000000..043292ee --- /dev/null +++ b/src/frontend/EmuThread.cpp @@ -0,0 +1,11 @@ +#include + +EmuThread::EmuThread(QObject* parent_object) noexcept : QThread(parent_object) {} + +[[noreturn]] void EmuThread::run() noexcept { + while (true) { + if (!core.pause) { + core.Run(0.5, 0.5); + } + } +} \ No newline at end of file diff --git a/src/frontend/EmuThread.hpp b/src/frontend/EmuThread.hpp new file mode 100644 index 00000000..215bcdbb --- /dev/null +++ b/src/frontend/EmuThread.hpp @@ -0,0 +1,36 @@ +#pragma once +#include +#include + +class EmuThread : public QThread +{ + Q_OBJECT + +public: + explicit EmuThread(QObject* parent_object) noexcept; + + [[noreturn]] void run() noexcept override; + + n64::Core core; + bool running = false; + + void TogglePause() + { + running = !running; + } + + void Reset() + { + running = false; + core.Stop(); + core.LoadROM(core.rom); + running = true; + } + + void Stop() + { + core.rom = {}; + running = false; + core.Stop(); + } +}; \ No newline at end of file diff --git a/src/frontend/KaizenQt.cpp b/src/frontend/KaizenQt.cpp new file mode 100644 index 00000000..bd394cb0 --- /dev/null +++ b/src/frontend/KaizenQt.cpp @@ -0,0 +1,28 @@ +#include +#include +#include + +KaizenQt::KaizenQt() noexcept + : mainWindow(new MainWindowController), + emuThread(new EmuThread(mainWindow)) +{ + ConnectMainWindowSignalsToSlots(); + + mainWindow->show(); +} + +void KaizenQt::ConnectMainWindowSignalsToSlots() noexcept +{ + connect(mainWindow, &MainWindowController::OpenROM, this, &KaizenQt::LoadROM); + connect(mainWindow, &MainWindowController::Exit, this, []() { + QApplication::quit(); + }); + connect(mainWindow, &MainWindowController::Reset, emuThread, &EmuThread::Reset); + connect(mainWindow, &MainWindowController::Stop, emuThread, &EmuThread::Stop); + connect(mainWindow, &MainWindowController::Pause, emuThread, &EmuThread::TogglePause); +} + +void KaizenQt::LoadROM(const QString& file_name) noexcept +{ + emuThread->core.LoadROM(file_name.toStdString()); +} diff --git a/src/frontend/KaizenQt.hpp b/src/frontend/KaizenQt.hpp new file mode 100644 index 00000000..9d622a02 --- /dev/null +++ b/src/frontend/KaizenQt.hpp @@ -0,0 +1,14 @@ +#pragma once +#include +#include + +class KaizenQt : public QObject { + Q_OBJECT +public: + KaizenQt() noexcept; + void LoadROM(const QString& path) noexcept; +private: + void ConnectMainWindowSignalsToSlots() noexcept; + MainWindowController* mainWindow; + EmuThread* emuThread; +}; \ No newline at end of file diff --git a/src/frontend/MainWindow.cpp b/src/frontend/MainWindow.cpp new file mode 100644 index 00000000..678a0338 --- /dev/null +++ b/src/frontend/MainWindow.cpp @@ -0,0 +1,54 @@ +#include +#include +#include + +MainWindowController::MainWindowController() noexcept +{ + view.setupUi(this); + ConnectSignalsToSlots(); +} + +void MainWindowController::ConnectSignalsToSlots() noexcept +{ + connect(view.actionOpen, &QAction::triggered, this, [this]() { + QString file_name = QFileDialog::getOpenFileName(this); + + if (!file_name.isEmpty()) + { + view.actionPause->setEnabled(true); + view.actionReset->setEnabled(true); + view.actionStop->setEnabled(true); + emit OpenROM(file_name); + } + }); + + connect(view.actionExit, &QAction::triggered, this, [this]() { + emit Exit(); + }); + + connect(view.actionReset, &QAction::triggered, this, [this]() { + emit Reset(); + }); + + connect(view.actionStop, &QAction::triggered, this, [this]() { + view.actionPause->setDisabled(true); + view.actionReset->setDisabled(true); + view.actionStop->setDisabled(true); + emit Stop(); + }); + + connect(view.actionPause, &QAction::triggered, this, [this]() { + textPauseToggle = !textPauseToggle; + view.actionPause->setText(textPauseToggle ? "Resume" : "Pause"); + emit Pause(); + }); + + connect(view.actionAbout, &QAction::triggered, this, [this]() { + QMessageBox::about( + this, tr("About Kaizen"), + tr("Kaizen is a Nintendo 64 emulator that strives to offer a friendly user " + "experience and great compatibility.\n" + "sliice is licensed under the BSD 3-clause license.\n" + "Nintendo 64 is a registered trademarks of Nintendo Co., Ltd.")); + }); +} \ No newline at end of file diff --git a/src/frontend/MainWindow.hpp b/src/frontend/MainWindow.hpp new file mode 100644 index 00000000..a8695200 --- /dev/null +++ b/src/frontend/MainWindow.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include "ui_mainwindow.h" + +class MainWindowController : public QMainWindow +{ + Q_OBJECT + +public: + MainWindowController() noexcept; + +private: + void ConnectSignalsToSlots() noexcept; + + Ui::MainWindow view; + bool textPauseToggle = false; + +signals: + void OpenROM(const QString& rom_file); + void Exit(); + void Reset(); + void Stop(); + void Pause(); +}; \ No newline at end of file diff --git a/src/frontend/main.cpp b/src/frontend/main.cpp index a90ecc21..a8d34e1d 100644 --- a/src/frontend/main.cpp +++ b/src/frontend/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include int main(int argc, char** argv) { QApplication app(argc, argv); @@ -12,5 +13,10 @@ int main(int argc, char** argv) { parser.addHelpOption(); parser.addPositionalArgument("rom", "Rom to launch from command-line"); parser.process(app); + + KaizenQt kaizenQt; + if (!parser.positionalArguments().isEmpty()) + kaizenQt.LoadROM(parser.positionalArguments().first()); + return app.exec(); } \ No newline at end of file diff --git a/src/frontend/mainwindow.ui b/src/frontend/mainwindow.ui new file mode 100644 index 00000000..1c8fc3a4 --- /dev/null +++ b/src/frontend/mainwindow.ui @@ -0,0 +1,124 @@ + + + MainWindow + + + + 0 + 0 + 800 + 600 + + + + Kaizen + + + + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + + 0 + 0 + 800 + 21 + + + + + File + + + + + + + Emulation + + + + + + + + Help + + + + + + + + + + + About Kaizen + + + About this emulator + + + + + Open... + + + Open a ROM + + + Ctrl+O + + + + + Exit + + + Quit the emulator + + + + + Pause + + + Pause the emulation + + + + + Reset + + + Reset the emulation + + + + + Stop + + + Stop the emulation + + + + + +