UI itself is usable
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
11
src/frontend/EmuThread.cpp
Normal file
11
src/frontend/EmuThread.cpp
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
36
src/frontend/EmuThread.hpp
Normal file
36
src/frontend/EmuThread.hpp
Normal 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
28
src/frontend/KaizenQt.cpp
Normal 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
14
src/frontend/KaizenQt.hpp
Normal 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;
|
||||
};
|
||||
54
src/frontend/MainWindow.cpp
Normal file
54
src/frontend/MainWindow.cpp
Normal 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."));
|
||||
});
|
||||
}
|
||||
24
src/frontend/MainWindow.hpp
Normal file
24
src/frontend/MainWindow.hpp
Normal 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();
|
||||
};
|
||||
@@ -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
124
src/frontend/mainwindow.ui
Normal 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>
|
||||
Reference in New Issue
Block a user