UI itself is usable

This commit is contained in:
Simone
2024-01-18 13:13:05 +01:00
parent af7a6c004b
commit 25d1e4c51f
10 changed files with 311 additions and 4 deletions

View File

@@ -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<Interpreter>();
}
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) {

View File

@@ -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)

View File

@@ -0,0 +1,11 @@
#include <EmuThread.hpp>
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);
}
}
}

View File

@@ -0,0 +1,36 @@
#pragma once
#include <QThread>
#include <Core.hpp>
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();
}
};

28
src/frontend/KaizenQt.cpp Normal file
View File

@@ -0,0 +1,28 @@
#include <KaizenQt.hpp>
#include <QMessageBox>
#include <QApplication>
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());
}

14
src/frontend/KaizenQt.hpp Normal file
View File

@@ -0,0 +1,14 @@
#pragma once
#include <MainWindow.hpp>
#include <EmuThread.hpp>
class KaizenQt : public QObject {
Q_OBJECT
public:
KaizenQt() noexcept;
void LoadROM(const QString& path) noexcept;
private:
void ConnectMainWindowSignalsToSlots() noexcept;
MainWindowController* mainWindow;
EmuThread* emuThread;
};

View File

@@ -0,0 +1,54 @@
#include <MainWindow.hpp>
#include <QFileDialog>
#include <QMessageBox>
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."));
});
}

View File

@@ -0,0 +1,24 @@
#pragma once
#include <QMainWindow>
#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();
};

View File

@@ -1,6 +1,7 @@
#include <QApplication>
#include <QCommandLineParser>
#include <QCommandLineOption>
#include <KaizenQt.hpp>
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();
}

124
src/frontend/mainwindow.ui Normal file
View File

@@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>600</height>
</rect>
</property>
<property name="windowTitle">
<string>Kaizen</string>
</property>
<widget class="QWidget" name="centralwidget">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
</layout>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>800</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string>File</string>
</property>
<addaction name="actionOpen"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuEmulation">
<property name="title">
<string>Emulation</string>
</property>
<addaction name="actionPause"/>
<addaction name="actionReset"/>
<addaction name="actionStop"/>
</widget>
<widget class="QMenu" name="menuAbout">
<property name="title">
<string>Help</string>
</property>
<addaction name="actionAbout"/>
</widget>
<addaction name="menuFile"/>
<addaction name="menuEmulation"/>
<addaction name="menuAbout"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<action name="actionAbout">
<property name="text">
<string>About Kaizen</string>
</property>
<property name="statusTip">
<string>About this emulator</string>
</property>
</action>
<action name="actionOpen">
<property name="text">
<string>Open...</string>
</property>
<property name="statusTip">
<string>Open a ROM</string>
</property>
<property name="shortcut">
<string>Ctrl+O</string>
</property>
</action>
<action name="actionExit">
<property name="text">
<string>Exit</string>
</property>
<property name="statusTip">
<string>Quit the emulator</string>
</property>
</action>
<action name="actionPause">
<property name="text">
<string>Pause</string>
</property>
<property name="statusTip">
<string>Pause the emulation</string>
</property>
</action>
<action name="actionReset">
<property name="text">
<string>Reset</string>
</property>
<property name="statusTip">
<string>Reset the emulation</string>
</property>
</action>
<action name="actionStop">
<property name="text">
<string>Stop</string>
</property>
<property name="statusTip">
<string>Stop the emulation</string>
</property>
</action>
</widget>
<resources/>
<connections/>
</ui>