mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 22:55:40 +12:00
commit
9bc46229c6
7 changed files with 248 additions and 26 deletions
|
@ -185,8 +185,8 @@ set(RENDERER_SW_SOURCE_FILES src/core/renderer_sw/renderer_sw.cpp)
|
||||||
|
|
||||||
# Frontend source files
|
# Frontend source files
|
||||||
if(ENABLE_QT_GUI)
|
if(ENABLE_QT_GUI)
|
||||||
set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp src/panda_qt/main_window.cpp)
|
set(FRONTEND_SOURCE_FILES src/panda_qt/main.cpp src/panda_qt/screen.cpp src/panda_qt/main_window.cpp src/panda_qt/about_window.cpp)
|
||||||
set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp include/panda_qt/main_window.hpp)
|
set(FRONTEND_HEADER_FILES include/panda_qt/screen.hpp include/panda_qt/main_window.hpp include/panda_qt/about_window.hpp)
|
||||||
|
|
||||||
source_group("Source Files\\Qt" FILES ${FRONTEND_SOURCE_FILES})
|
source_group("Source Files\\Qt" FILES ${FRONTEND_SOURCE_FILES})
|
||||||
source_group("Header Files\\Qt" FILES ${FRONTEND_HEADER_FILES})
|
source_group("Header Files\\Qt" FILES ${FRONTEND_HEADER_FILES})
|
||||||
|
@ -429,7 +429,7 @@ if(ENABLE_QT_GUI)
|
||||||
qt_add_resources(Alber "app_images"
|
qt_add_resources(Alber "app_images"
|
||||||
PREFIX "/"
|
PREFIX "/"
|
||||||
FILES
|
FILES
|
||||||
docs/img/rsob_icon.png
|
docs/img/rsob_icon.png docs/img/rstarstruck_icon.png
|
||||||
)
|
)
|
||||||
else()
|
else()
|
||||||
target_compile_definitions(Alber PUBLIC "PANDA3DS_FRONTEND_SDL=1")
|
target_compile_definitions(Alber PUBLIC "PANDA3DS_FRONTEND_SDL=1")
|
||||||
|
|
BIN
docs/img/rstarstruck_icon.png
Normal file
BIN
docs/img/rstarstruck_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.9 KiB |
|
@ -52,12 +52,14 @@ class Emulator {
|
||||||
// We bind gyro to right click + mouse movement
|
// We bind gyro to right click + mouse movement
|
||||||
bool holdingRightClick = false;
|
bool holdingRightClick = false;
|
||||||
|
|
||||||
|
public:
|
||||||
static constexpr u32 width = 400;
|
static constexpr u32 width = 400;
|
||||||
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
static constexpr u32 height = 240 * 2; // * 2 because 2 screens
|
||||||
ROMType romType = ROMType::None;
|
ROMType romType = ROMType::None;
|
||||||
bool running = false; // Is the emulator running a game?
|
bool running = false; // Is the emulator running a game?
|
||||||
bool programRunning = false; // Is the emulator program itself running?
|
bool programRunning = false; // Is the emulator program itself running?
|
||||||
|
|
||||||
|
private:
|
||||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||||
HttpServer httpServer;
|
HttpServer httpServer;
|
||||||
friend struct HttpServer;
|
friend struct HttpServer;
|
||||||
|
|
12
include/panda_qt/about_window.hpp
Normal file
12
include/panda_qt/about_window.hpp
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class AboutWindow : public QDialog {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
AboutWindow(QWidget* parent = nullptr);
|
||||||
|
};
|
|
@ -9,9 +9,12 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "emulator.hpp"
|
#include "emulator.hpp"
|
||||||
|
#include "panda_qt/about_window.hpp"
|
||||||
#include "panda_qt/screen.hpp"
|
#include "panda_qt/screen.hpp"
|
||||||
|
#include "services/hid.hpp"
|
||||||
|
|
||||||
class MainWindow : public QMainWindow {
|
class MainWindow : public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -21,6 +24,27 @@ class MainWindow : public QMainWindow {
|
||||||
System = 0,
|
System = 0,
|
||||||
Light = 1,
|
Light = 1,
|
||||||
Dark = 2,
|
Dark = 2,
|
||||||
|
GreetingsCat = 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Types of messages we might send from the GUI thread to the emulator thread
|
||||||
|
enum class MessageType {
|
||||||
|
LoadROM, Reset, Pause, Resume, TogglePause, DumpRomFS, PressKey, ReleaseKey
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tagged union representing our message queue messages
|
||||||
|
struct EmulatorMessage {
|
||||||
|
MessageType type;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
std::filesystem::path* p;
|
||||||
|
} path;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
u32 key;
|
||||||
|
} key;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
// This would normally be an std::unique_ptr but it's shared between threads so definitely not
|
// This would normally be an std::unique_ptr but it's shared between threads so definitely not
|
||||||
|
@ -28,12 +52,12 @@ class MainWindow : public QMainWindow {
|
||||||
std::thread emuThread;
|
std::thread emuThread;
|
||||||
|
|
||||||
std::atomic<bool> appRunning = true; // Is the application itself running?
|
std::atomic<bool> appRunning = true; // Is the application itself running?
|
||||||
std::mutex messageQueueMutex; // Used for synchronizing messages between the emulator and UI
|
// Used for synchronizing messages between the emulator and UI
|
||||||
std::filesystem::path romToLoad = "";
|
std::mutex messageQueueMutex;
|
||||||
|
std::vector<EmulatorMessage> messageQueue;
|
||||||
bool needToLoadROM = false;
|
|
||||||
|
|
||||||
ScreenWidget screen;
|
ScreenWidget screen;
|
||||||
|
AboutWindow* aboutWindow;
|
||||||
QComboBox* themeSelect = nullptr;
|
QComboBox* themeSelect = nullptr;
|
||||||
QMenuBar* menuBar = nullptr;
|
QMenuBar* menuBar = nullptr;
|
||||||
|
|
||||||
|
@ -43,6 +67,9 @@ class MainWindow : public QMainWindow {
|
||||||
void emuThreadMainLoop();
|
void emuThreadMainLoop();
|
||||||
void selectROM();
|
void selectROM();
|
||||||
void dumpRomFS();
|
void dumpRomFS();
|
||||||
|
void showAboutMenu();
|
||||||
|
void sendMessage(const EmulatorMessage& message);
|
||||||
|
void dispatchMessage(const EmulatorMessage& message);
|
||||||
|
|
||||||
// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer
|
// Tracks whether we are using an OpenGL-backed renderer or a Vulkan-backed renderer
|
||||||
bool usingGL = false;
|
bool usingGL = false;
|
||||||
|
@ -51,4 +78,7 @@ class MainWindow : public QMainWindow {
|
||||||
public:
|
public:
|
||||||
MainWindow(QApplication* app, QWidget* parent = nullptr);
|
MainWindow(QApplication* app, QWidget* parent = nullptr);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
|
void keyPressEvent(QKeyEvent* event) override;
|
||||||
|
void keyReleaseEvent(QKeyEvent* event) override;
|
||||||
};
|
};
|
62
src/panda_qt/about_window.cpp
Normal file
62
src/panda_qt/about_window.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
#include "panda_qt/about_window.hpp"
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QTextEdit>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
|
// Based on https://github.com/dolphin-emu/dolphin/blob/master/Source/Core/DolphinQt/AboutDialog.cpp
|
||||||
|
|
||||||
|
AboutWindow::AboutWindow(QWidget* parent) : QDialog(parent) {
|
||||||
|
resize(200, 200);
|
||||||
|
|
||||||
|
setWindowTitle(tr("About Panda3DS"));
|
||||||
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
|
const QString text =
|
||||||
|
QStringLiteral(R"(
|
||||||
|
<p style='font-size:38pt; font-weight:400;'>Panda3DS</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
%ABOUT_PANDA3DS%<br>
|
||||||
|
<a href='https://panda3ds.com/'>%SUPPORT%</a><br>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a>%AUTHORS%</a>
|
||||||
|
</p>
|
||||||
|
)")
|
||||||
|
.replace(QStringLiteral("%ABOUT_PANDA3DS%"), tr("Panda3DS is a free and open source Nintendo 3DS emulator, for Windows, MacOS and Linux"))
|
||||||
|
.replace(QStringLiteral("%SUPPORT%"), tr("Visit panda3ds.com for help with Panda3DS and links to our official support sites."))
|
||||||
|
.replace(
|
||||||
|
QStringLiteral("%AUTHORS%"), tr("Panda3DS is developed by volunteers in their spare time. Below is a list of some of these"
|
||||||
|
" volunteers who've agreed to be listed here, in no particular order.<br>If you think you should be "
|
||||||
|
"listed here too, please inform us<br><br>"
|
||||||
|
"- Peach (wheremyfoodat)<br>"
|
||||||
|
"- noumidev<br>"
|
||||||
|
"- liuk707<br>"
|
||||||
|
"- Wunk<br>"
|
||||||
|
"- marysaka<br>"
|
||||||
|
"- Sky<br>"
|
||||||
|
"- merryhime<br>"
|
||||||
|
"- TGP17<br>")
|
||||||
|
);
|
||||||
|
|
||||||
|
QLabel* textLabel = new QLabel(text);
|
||||||
|
textLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
textLabel->setOpenExternalLinks(true);
|
||||||
|
|
||||||
|
QLabel* logo = new QLabel();
|
||||||
|
logo->setPixmap(QPixmap(":/docs/img/rstarstruck_icon.png"));
|
||||||
|
logo->setContentsMargins(30, 0, 30, 0);
|
||||||
|
|
||||||
|
QVBoxLayout* mainLayout = new QVBoxLayout;
|
||||||
|
QHBoxLayout* hLayout = new QHBoxLayout;
|
||||||
|
|
||||||
|
setLayout(mainLayout);
|
||||||
|
mainLayout->addLayout(hLayout);
|
||||||
|
|
||||||
|
hLayout->setAlignment(Qt::AlignLeft);
|
||||||
|
hLayout->addWidget(logo);
|
||||||
|
hLayout->addWidget(textLabel);
|
||||||
|
}
|
|
@ -20,28 +20,41 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
|
||||||
auto fileMenu = menuBar->addMenu(tr("File"));
|
auto fileMenu = menuBar->addMenu(tr("File"));
|
||||||
auto emulationMenu = menuBar->addMenu(tr("Emulation"));
|
auto emulationMenu = menuBar->addMenu(tr("Emulation"));
|
||||||
auto toolsMenu = menuBar->addMenu(tr("Tools"));
|
auto toolsMenu = menuBar->addMenu(tr("Tools"));
|
||||||
auto helpMenu = menuBar->addMenu(tr("Help"));
|
|
||||||
auto aboutMenu = menuBar->addMenu(tr("About"));
|
auto aboutMenu = menuBar->addMenu(tr("About"));
|
||||||
|
|
||||||
// Create and bind actions for them
|
// Create and bind actions for them
|
||||||
auto pandaAction = fileMenu->addAction(tr("panda..."));
|
auto pandaAction = fileMenu->addAction(tr("panda..."));
|
||||||
connect(pandaAction, &QAction::triggered, this, &MainWindow::selectROM);
|
connect(pandaAction, &QAction::triggered, this, &MainWindow::selectROM);
|
||||||
|
|
||||||
|
auto pauseAction = emulationMenu->addAction(tr("Pause"));
|
||||||
|
auto resumeAction = emulationMenu->addAction(tr("Resume"));
|
||||||
|
auto resetAction = emulationMenu->addAction(tr("Reset"));
|
||||||
|
connect(pauseAction, &QAction::triggered, this, [this]() { sendMessage(EmulatorMessage{.type = MessageType::Pause}); });
|
||||||
|
connect(resumeAction, &QAction::triggered, this, [this]() { sendMessage(EmulatorMessage{.type = MessageType::Resume}); });
|
||||||
|
connect(resetAction, &QAction::triggered, this, [this]() { sendMessage(EmulatorMessage{.type = MessageType::Reset}); });
|
||||||
|
|
||||||
auto dumpRomFSAction = toolsMenu->addAction(tr("Dump RomFS"));
|
auto dumpRomFSAction = toolsMenu->addAction(tr("Dump RomFS"));
|
||||||
connect(dumpRomFSAction, &QAction::triggered, this, &MainWindow::dumpRomFS);
|
connect(dumpRomFSAction, &QAction::triggered, this, &MainWindow::dumpRomFS);
|
||||||
|
|
||||||
|
auto aboutAction = aboutMenu->addAction(tr("About Panda3DS"));
|
||||||
|
connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutMenu);
|
||||||
|
|
||||||
// Set up theme selection
|
// Set up theme selection
|
||||||
setTheme(Theme::Dark);
|
setTheme(Theme::Dark);
|
||||||
themeSelect = new QComboBox(this);
|
themeSelect = new QComboBox(this);
|
||||||
themeSelect->addItem(tr("System"));
|
themeSelect->addItem(tr("System"));
|
||||||
themeSelect->addItem(tr("Light"));
|
themeSelect->addItem(tr("Light"));
|
||||||
themeSelect->addItem(tr("Dark"));
|
themeSelect->addItem(tr("Dark"));
|
||||||
|
themeSelect->addItem(tr("Greetings Cat"));
|
||||||
themeSelect->setCurrentIndex(static_cast<int>(currentTheme));
|
themeSelect->setCurrentIndex(static_cast<int>(currentTheme));
|
||||||
|
|
||||||
themeSelect->setGeometry(40, 40, 100, 50);
|
themeSelect->setGeometry(40, 40, 100, 50);
|
||||||
themeSelect->show();
|
themeSelect->show();
|
||||||
connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) { setTheme(static_cast<Theme>(index)); });
|
connect(themeSelect, &QComboBox::currentIndexChanged, this, [&](int index) { setTheme(static_cast<Theme>(index)); });
|
||||||
|
|
||||||
|
// Set up misc objects
|
||||||
|
aboutWindow = new AboutWindow(nullptr);
|
||||||
|
|
||||||
emu = new Emulator();
|
emu = new Emulator();
|
||||||
emu->setOutputSize(screen.surfaceWidth, screen.surfaceHeight);
|
emu->setOutputSize(screen.surfaceWidth, screen.surfaceHeight);
|
||||||
|
|
||||||
|
@ -73,17 +86,21 @@ void MainWindow::emuThreadMainLoop() {
|
||||||
{
|
{
|
||||||
std::unique_lock lock(messageQueueMutex);
|
std::unique_lock lock(messageQueueMutex);
|
||||||
|
|
||||||
if (needToLoadROM) {
|
// Dispatch all messages in the message queue
|
||||||
needToLoadROM = false;
|
if (!messageQueue.empty()) {
|
||||||
|
for (const auto& msg : messageQueue) {
|
||||||
bool success = emu->loadROM(romToLoad);
|
dispatchMessage(msg);
|
||||||
if (!success) {
|
|
||||||
printf("Failed to load ROM");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
messageQueue.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
emu->runFrame();
|
emu->runFrame();
|
||||||
|
if (emu->romType != ROMType::None) {
|
||||||
|
emu->getServiceManager().getHID().updateInputs(emu->getTicks());
|
||||||
|
}
|
||||||
|
|
||||||
swapEmuBuffer();
|
swapEmuBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,23 +119,15 @@ void MainWindow::swapEmuBuffer() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::selectROM() {
|
void MainWindow::selectROM() {
|
||||||
// Are we already waiting for a ROM to be loaded? Then complain about it!
|
|
||||||
{
|
|
||||||
std::unique_lock lock(messageQueueMutex);
|
|
||||||
if (needToLoadROM) {
|
|
||||||
QMessageBox::warning(this, tr("Already loading ROM"), tr("Panda3DS is already busy loading a ROM, please wait"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto path =
|
auto path =
|
||||||
QFileDialog::getOpenFileName(this, tr("Select 3DS ROM to load"), "", tr("Nintendo 3DS ROMs (*.3ds *.cci *.cxi *.app *.3dsx *.elf *.axf)"));
|
QFileDialog::getOpenFileName(this, tr("Select 3DS ROM to load"), "", tr("Nintendo 3DS ROMs (*.3ds *.cci *.cxi *.app *.3dsx *.elf *.axf)"));
|
||||||
|
|
||||||
if (!path.isEmpty()) {
|
if (!path.isEmpty()) {
|
||||||
std::unique_lock lock(messageQueueMutex);
|
std::filesystem::path* p = new std::filesystem::path(path.toStdU16String());
|
||||||
|
|
||||||
romToLoad = path.toStdU16String();
|
EmulatorMessage message{.type = MessageType::LoadROM};
|
||||||
needToLoadROM = true;
|
message.path.p = p;
|
||||||
|
sendMessage(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,9 +141,16 @@ MainWindow::~MainWindow() {
|
||||||
|
|
||||||
delete emu;
|
delete emu;
|
||||||
delete menuBar;
|
delete menuBar;
|
||||||
|
delete aboutWindow;
|
||||||
delete themeSelect;
|
delete themeSelect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send a message to the emulator thread. Lock the mutex and just push back to the vector.
|
||||||
|
void MainWindow::sendMessage(const EmulatorMessage& message) {
|
||||||
|
std::unique_lock lock(messageQueueMutex);
|
||||||
|
messageQueue.push_back(message);
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindow::setTheme(Theme theme) {
|
void MainWindow::setTheme(Theme theme) {
|
||||||
currentTheme = theme;
|
currentTheme = theme;
|
||||||
|
|
||||||
|
@ -183,6 +199,28 @@ void MainWindow::setTheme(Theme theme) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case Theme::GreetingsCat: {
|
||||||
|
QApplication::setStyle(QStyleFactory::create("Fusion"));
|
||||||
|
|
||||||
|
QPalette p;
|
||||||
|
p.setColor(QPalette::Window, QColor(250, 207, 228));
|
||||||
|
p.setColor(QPalette::WindowText, QColor(225, 22, 137));
|
||||||
|
p.setColor(QPalette::Base, QColor(250, 207, 228));
|
||||||
|
p.setColor(QPalette::AlternateBase, QColor(250, 207, 228));
|
||||||
|
p.setColor(QPalette::ToolTipBase, QColor(225, 22, 137));
|
||||||
|
p.setColor(QPalette::ToolTipText, QColor(225, 22, 137));
|
||||||
|
p.setColor(QPalette::Text, QColor(225, 22, 137));
|
||||||
|
p.setColor(QPalette::Button, QColor(250, 207, 228));
|
||||||
|
p.setColor(QPalette::ButtonText, QColor(225, 22, 137));
|
||||||
|
p.setColor(QPalette::BrightText, Qt::black);
|
||||||
|
p.setColor(QPalette::Link, QColor(42, 130, 218));
|
||||||
|
|
||||||
|
p.setColor(QPalette::Highlight, QColor(42, 130, 218));
|
||||||
|
p.setColor(QPalette::HighlightedText, Qt::black);
|
||||||
|
qApp->setPalette(p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
case Theme::System: {
|
case Theme::System: {
|
||||||
qApp->setPalette(this->style()->standardPalette());
|
qApp->setPalette(this->style()->standardPalette());
|
||||||
qApp->setStyle(QStyleFactory::create("WindowsVista"));
|
qApp->setStyle(QStyleFactory::create("WindowsVista"));
|
||||||
|
@ -225,4 +263,82 @@ void MainWindow::dumpRomFS() {
|
||||||
QMessageBox::warning(this, tr("No RomFS found"), tr("No RomFS partition was found in the loaded app"));
|
QMessageBox::warning(this, tr("No RomFS found"), tr("No RomFS partition was found in the loaded app"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::showAboutMenu() {
|
||||||
|
AboutWindow about(this);
|
||||||
|
about.exec();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::dispatchMessage(const EmulatorMessage& message) {
|
||||||
|
switch (message.type) {
|
||||||
|
case MessageType::LoadROM:
|
||||||
|
emu->loadROM(*message.path.p);
|
||||||
|
// Clean up the allocated path
|
||||||
|
delete message.path.p;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MessageType::Pause: emu->pause(); break;
|
||||||
|
case MessageType::Resume: emu->resume(); break;
|
||||||
|
case MessageType::TogglePause: emu->togglePause(); break;
|
||||||
|
case MessageType::Reset: emu->reset(Emulator::ReloadOption::Reload); break;
|
||||||
|
case MessageType::PressKey: emu->getServiceManager().getHID().pressKey(message.key.key); break;
|
||||||
|
case MessageType::ReleaseKey: emu->getServiceManager().getHID().releaseKey(message.key.key); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::keyPressEvent(QKeyEvent* event) {
|
||||||
|
auto pressKey = [this](u32 key) {
|
||||||
|
EmulatorMessage message{.type = MessageType::PressKey};
|
||||||
|
message.key.key = key;
|
||||||
|
|
||||||
|
sendMessage(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (event->key()) {
|
||||||
|
case Qt::Key_L: pressKey(HID::Keys::A); break;
|
||||||
|
case Qt::Key_K: pressKey(HID::Keys::B); break;
|
||||||
|
case Qt::Key_O: pressKey(HID::Keys::X); break;
|
||||||
|
case Qt::Key_I: pressKey(HID::Keys::Y); break;
|
||||||
|
|
||||||
|
case Qt::Key_Q: pressKey(HID::Keys::L); break;
|
||||||
|
case Qt::Key_P: pressKey(HID::Keys::R); break;
|
||||||
|
|
||||||
|
case Qt::Key_Right: pressKey(HID::Keys::Right); break;
|
||||||
|
case Qt::Key_Left: pressKey(HID::Keys::Left); break;
|
||||||
|
case Qt::Key_Up: pressKey(HID::Keys::Up); break;
|
||||||
|
case Qt::Key_Down: pressKey(HID::Keys::Down); break;
|
||||||
|
|
||||||
|
case Qt::Key_Return: pressKey(HID::Keys::Start); break;
|
||||||
|
case Qt::Key_Backspace: pressKey(HID::Keys::Select); break;
|
||||||
|
case Qt::Key_F4: sendMessage(EmulatorMessage{.type = MessageType::TogglePause}); break;
|
||||||
|
case Qt::Key_F5: sendMessage(EmulatorMessage{.type = MessageType::Reset}); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::keyReleaseEvent(QKeyEvent* event) {
|
||||||
|
auto releaseKey = [this](u32 key) {
|
||||||
|
EmulatorMessage message{.type = MessageType::ReleaseKey};
|
||||||
|
message.key.key = key;
|
||||||
|
|
||||||
|
sendMessage(message);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (event->key()) {
|
||||||
|
case Qt::Key_L: releaseKey(HID::Keys::A); break;
|
||||||
|
case Qt::Key_K: releaseKey(HID::Keys::B); break;
|
||||||
|
case Qt::Key_O: releaseKey(HID::Keys::X); break;
|
||||||
|
case Qt::Key_I: releaseKey(HID::Keys::Y); break;
|
||||||
|
|
||||||
|
case Qt::Key_Q: releaseKey(HID::Keys::L); break;
|
||||||
|
case Qt::Key_P: releaseKey(HID::Keys::R); break;
|
||||||
|
|
||||||
|
case Qt::Key_Right: releaseKey(HID::Keys::Right); break;
|
||||||
|
case Qt::Key_Left: releaseKey(HID::Keys::Left); break;
|
||||||
|
case Qt::Key_Up: releaseKey(HID::Keys::Up); break;
|
||||||
|
case Qt::Key_Down: releaseKey(HID::Keys::Down); break;
|
||||||
|
|
||||||
|
case Qt::Key_Return: releaseKey(HID::Keys::Start); break;
|
||||||
|
case Qt::Key_Backspace: releaseKey(HID::Keys::Select); break;
|
||||||
|
}
|
||||||
}
|
}
|
Loading…
Add table
Reference in a new issue