Merge branch 'wheremyfoodat:master' into ui

This commit is contained in:
Gabriel Machado 2023-12-16 23:29:19 -04:00 committed by GitHub
commit b42c7a122b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 190 additions and 14 deletions

View file

@ -2,6 +2,7 @@
#include "ipc.hpp"
#include "kernel.hpp"
#include <algorithm>
#include <vector>
namespace APTCommands {
@ -311,12 +312,14 @@ void APTService::setApplicationCpuTimeLimit(u32 messagePointer) {
log("APT::SetApplicationCpuTimeLimit (percentage = %d%%)\n", percentage);
if (percentage < 5 || percentage > 89 || fixed != 1) {
Helpers::panic("Invalid parameters passed to APT::SetApplicationCpuTimeLimit");
} else {
mem.write32(messagePointer, IPC::responseHeader(0x4F, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
cpuTimeLimit = percentage;
Helpers::warn("Invalid parameter passed to APT::SetApplicationCpuTimeLimit: (percentage, fixed) = (%d, %d)\n", percentage, fixed);
// TODO: Does the clamp operation happen? Verify with getApplicationCpuTimeLimit on hardware
percentage = std::clamp<u32>(percentage, 5, 89);
}
mem.write32(messagePointer, IPC::responseHeader(0x4F, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
cpuTimeLimit = percentage;
}
void APTService::getApplicationCpuTimeLimit(u32 messagePointer) {

View file

@ -51,6 +51,31 @@ void LuaManager::loadFile(const char* path) {
}
}
void LuaManager::loadString(const std::string& code) {
// Initialize Lua if it has not been initialized
if (!initialized) {
initialize();
}
// If init failed, don't execute
if (!initialized) {
printf("Lua initialization failed, file won't run\n");
haveScript = false;
return;
}
int status = luaL_loadstring(L, code.c_str()); // load Lua script
int ret = lua_pcall(L, 0, 0, 0); // tell Lua to run the script
if (ret != 0) {
haveScript = false;
fprintf(stderr, "%s\n", lua_tostring(L, -1)); // tell us what mistake we made
} else {
haveScript = true;
}
}
void LuaManager::signalEventInternal(LuaEvent e) {
lua_getglobal(L, "eventHandler"); // We want to call the event handler
lua_pushnumber(L, static_cast<int>(e)); // Push event type

View file

@ -2,6 +2,7 @@
#include <QFileDialog>
#include <cstdio>
#include <fstream>
MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent), screen(this) {
setWindowTitle("Alber");
@ -23,8 +24,10 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
auto aboutMenu = menuBar->addMenu(tr("About"));
// Create and bind actions for them
auto pandaAction = fileMenu->addAction(tr("Load game"));
connect(pandaAction, &QAction::triggered, this, &MainWindow::selectROM);
auto loadGameAction = fileMenu->addAction(tr("Load game"));
auto loadLuaAction = fileMenu->addAction(tr("Load Lua script"));
connect(loadGameAction, &QAction::triggered, this, &MainWindow::selectROM);
connect(loadLuaAction, &QAction::triggered, this, &MainWindow::selectLuaFile);
auto pauseAction = emulationMenu->addAction(tr("Pause"));
auto resumeAction = emulationMenu->addAction(tr("Resume"));
@ -36,7 +39,9 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
connect(configureAction, &QAction::triggered, this, [this]() { configWindow->show(); });
auto dumpRomFSAction = toolsMenu->addAction(tr("Dump RomFS"));
auto luaEditorAction = toolsMenu->addAction(tr("Open Lua Editor"));
connect(dumpRomFSAction, &QAction::triggered, this, &MainWindow::dumpRomFS);
connect(luaEditorAction, &QAction::triggered, this, &MainWindow::openLuaEditor);
auto aboutAction = aboutMenu->addAction(tr("About Panda3DS"));
connect(aboutAction, &QAction::triggered, this, &MainWindow::showAboutMenu);
@ -44,6 +49,7 @@ MainWindow::MainWindow(QApplication* app, QWidget* parent) : QMainWindow(parent)
// Set up misc objects
aboutWindow = new AboutWindow(nullptr);
configWindow = new ConfigWindow(this);
luaEditor = new TextEditorWindow(this, "script.lua", "");
emu = new Emulator();
emu->setOutputSize(screen.surfaceWidth, screen.surfaceHeight);
@ -121,6 +127,34 @@ void MainWindow::selectROM() {
}
}
void MainWindow::selectLuaFile() {
auto path = QFileDialog::getOpenFileName(this, tr("Select Lua script to load"), "", tr("Lua scripts (*.lua *.txt)"));
if (!path.isEmpty()) {
std::ifstream file(std::filesystem::path(path.toStdU16String()), std::ios::in);
if (file.fail()) {
printf("Failed to load selected lua file\n");
return;
}
// Read whole file into an std::string string
// Get file size, preallocate std::string to avoid furthermemory allocations
std::string code;
file.seekg(0, std::ios::end);
code.resize(file.tellg());
// Rewind and read the whole file
file.seekg(0, std::ios::beg);
file.read(&code[0], code.size());
file.close();
loadLuaScript(code);
// Copy the Lua script to the Lua editor
luaEditor->setText(code);
}
}
// Cleanup when the main window closes
MainWindow::~MainWindow() {
appRunning = false; // Set our running atomic to false in order to make the emulator thread stop, and join it
@ -133,6 +167,7 @@ MainWindow::~MainWindow() {
delete menuBar;
delete aboutWindow;
delete configWindow;
delete luaEditor;
}
// Send a message to the emulator thread. Lock the mutex and just push back to the vector.
@ -181,6 +216,8 @@ void MainWindow::showAboutMenu() {
about.exec();
}
void MainWindow::openLuaEditor() { luaEditor->show(); }
void MainWindow::dispatchMessage(const EmulatorMessage& message) {
switch (message.type) {
case MessageType::LoadROM:
@ -189,6 +226,11 @@ void MainWindow::dispatchMessage(const EmulatorMessage& message) {
delete message.path.p;
break;
case MessageType::LoadLuaScript:
emu->getLua().loadString(*message.string.str);
delete message.string.str;
break;
case MessageType::Pause: emu->pause(); break;
case MessageType::Resume: emu->resume(); break;
case MessageType::TogglePause: emu->togglePause(); break;
@ -253,3 +295,11 @@ void MainWindow::keyReleaseEvent(QKeyEvent* event) {
case Qt::Key_Backspace: releaseKey(HID::Keys::Select); break;
}
}
void MainWindow::loadLuaScript(const std::string& code) {
EmulatorMessage message{.type = MessageType::LoadLuaScript};
// Make a copy of the code on the heap to send via the message queue
message.string.str = new std::string(code);
sendMessage(message);
}

View file

@ -0,0 +1,44 @@
#include "panda_qt/text_editor.hpp"
#include <QPushButton>
#include <QVBoxLayout>
#include "panda_qt/main_window.hpp"
using namespace Zep;
TextEditorWindow::TextEditorWindow(QWidget* parent, const std::string& filename, const std::string& initialText)
: QDialog(parent), zepWidget(this, qApp->applicationDirPath().toStdString(), fontSize) {
resize(600, 600);
// Register our extensions
ZepRegressExCommand::Register(zepWidget.GetEditor());
ZepReplExCommand::Register(zepWidget.GetEditor(), &replProvider);
// Default to standard mode instead of vim mode, initialize text box
zepWidget.GetEditor().SetGlobalMode(Zep::ZepMode_Standard::StaticName());
zepWidget.GetEditor().InitWithText(filename, initialText);
// Layout for widgets
QVBoxLayout* mainLayout = new QVBoxLayout();
setLayout(mainLayout);
QPushButton* button = new QPushButton(tr("Load script"), this);
button->setFixedSize(100, 20);
// When the Load Script button is pressed, send the current text to the MainWindow, which will upload it to the emulator's lua object
connect(button, &QPushButton::pressed, this, [this]() {
if (parentWidget()) {
auto buffer = zepWidget.GetEditor().GetMRUBuffer();
const std::string text = buffer->GetBufferText(buffer->Begin(), buffer->End());
static_cast<MainWindow*>(parentWidget())->loadLuaScript(text);
} else {
// This should be unreachable, only here for safety purposes
printf("Text editor does not have any parent widget, click doesn't work :(\n");
}
});
mainLayout->addWidget(button);
mainLayout->addWidget(&zepWidget);
}

2
src/panda_qt/zep.cpp Normal file
View file

@ -0,0 +1,2 @@
#define ZEP_SINGLE_HEADER_BUILD
#include "zep.h"

View file

@ -57,4 +57,4 @@ public class GlobalConfig {
this.defaultValue = defaultValue;
}
}
}
}