UI itself is usable
This commit is contained in:
@@ -18,19 +18,21 @@ Core::Core() {
|
|||||||
if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) {
|
if(SDL_GameControllerAddMappingsFromFile("resources/gamecontrollerdb.txt") < 0) {
|
||||||
Util::warn("Failed to load game controller DB");
|
Util::warn("Failed to load game controller DB");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu = std::make_unique<Interpreter>();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Stop() {
|
void Core::Stop() {
|
||||||
cpu->Reset();
|
|
||||||
cpu->mem.Reset();
|
|
||||||
pause = true;
|
pause = true;
|
||||||
romLoaded = false;
|
romLoaded = false;
|
||||||
|
cpu->Reset();
|
||||||
|
cpu->mem.Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::LoadROM(const std::string& rom_) {
|
void Core::LoadROM(const std::string& rom_) {
|
||||||
|
pause = true;
|
||||||
rom = rom_;
|
rom = rom_;
|
||||||
cpu->Reset();
|
cpu->Reset();
|
||||||
pause = false;
|
|
||||||
romLoaded = true;
|
romLoaded = true;
|
||||||
|
|
||||||
std::string archive_types[] = {".zip",".7z",".rar",".tar"};
|
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.flash.Load(cpu->mem.saveType, rom);
|
||||||
cpu->mem.LoadSRAM(cpu->mem.saveType, rom);
|
cpu->mem.LoadSRAM(cpu->mem.saveType, rom);
|
||||||
PIF::ExecutePIF(cpu->mem, cpu->regs);
|
PIF::ExecutePIF(cpu->mem, cpu->regs);
|
||||||
|
pause = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Core::Run(float volumeL, float volumeR) {
|
void Core::Run(float volumeL, float volumeR) {
|
||||||
|
|||||||
@@ -50,7 +50,14 @@ set(CMAKE_AUTORCC ON)
|
|||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
|
||||||
add_executable(kaizen-qt
|
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
|
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)
|
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 <QApplication>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
#include <QCommandLineOption>
|
#include <QCommandLineOption>
|
||||||
|
#include <KaizenQt.hpp>
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
@@ -12,5 +13,10 @@ int main(int argc, char** argv) {
|
|||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
parser.addPositionalArgument("rom", "Rom to launch from command-line");
|
parser.addPositionalArgument("rom", "Rom to launch from command-line");
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
|
|
||||||
|
KaizenQt kaizenQt;
|
||||||
|
if (!parser.positionalArguments().isEmpty())
|
||||||
|
kaizenQt.LoadROM(parser.positionalArguments().first());
|
||||||
|
|
||||||
return app.exec();
|
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