mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 15:45:40 +12:00
Merge pull request #146 from OFFTKP/panda-1
Add /step http server command
This commit is contained in:
commit
9a71713b56
2 changed files with 80 additions and 5 deletions
|
@ -13,7 +13,7 @@
|
|||
|
||||
#include "helpers.hpp"
|
||||
|
||||
enum class HttpActionType { None, Screenshot, Key, TogglePause, Reset, LoadRom };
|
||||
enum class HttpActionType { None, Screenshot, Key, TogglePause, Reset, LoadRom, Step };
|
||||
|
||||
class Emulator;
|
||||
namespace httplib {
|
||||
|
@ -46,6 +46,7 @@ class HttpAction {
|
|||
static std::unique_ptr<HttpAction> createLoadRomAction(DeferredResponseWrapper& response, const std::filesystem::path& path, bool paused);
|
||||
static std::unique_ptr<HttpAction> createTogglePauseAction();
|
||||
static std::unique_ptr<HttpAction> createResetAction();
|
||||
static std::unique_ptr<HttpAction> createStepAction(DeferredResponseWrapper& response, int frames);
|
||||
};
|
||||
|
||||
struct HttpServer {
|
||||
|
@ -62,9 +63,11 @@ struct HttpServer {
|
|||
std::thread httpServerThread;
|
||||
std::queue<std::unique_ptr<HttpAction>> actionQueue;
|
||||
std::mutex actionQueueMutex;
|
||||
std::unique_ptr<HttpAction> currentStepAction {};
|
||||
|
||||
std::map<std::string, u32> keyMap;
|
||||
bool paused = false;
|
||||
int framesToRun = 0;
|
||||
|
||||
void startHttpServer();
|
||||
void pushAction(std::unique_ptr<HttpAction> action);
|
||||
|
|
|
@ -55,6 +55,18 @@ class HttpActionLoadRom : public HttpAction {
|
|||
bool getPaused() const { return paused; }
|
||||
};
|
||||
|
||||
class HttpActionStep : public HttpAction {
|
||||
DeferredResponseWrapper& response;
|
||||
int frames;
|
||||
|
||||
public:
|
||||
HttpActionStep(DeferredResponseWrapper& response, int frames)
|
||||
: HttpAction(HttpActionType::Step), response(response), frames(frames) {}
|
||||
|
||||
DeferredResponseWrapper& getResponse() { return response; }
|
||||
int getFrames() const { return frames; }
|
||||
};
|
||||
|
||||
std::unique_ptr<HttpAction> HttpAction::createScreenshotAction(DeferredResponseWrapper& response) {
|
||||
return std::make_unique<HttpActionScreenshot>(response);
|
||||
}
|
||||
|
@ -67,6 +79,10 @@ std::unique_ptr<HttpAction> HttpAction::createLoadRomAction(DeferredResponseWrap
|
|||
return std::make_unique<HttpActionLoadRom>(response, path, paused);
|
||||
}
|
||||
|
||||
std::unique_ptr<HttpAction> HttpAction::createStepAction(DeferredResponseWrapper& response, int frames) {
|
||||
return std::make_unique<HttpActionStep>(response, frames);
|
||||
}
|
||||
|
||||
HttpServer::HttpServer(Emulator* emulator)
|
||||
: emulator(emulator), server(std::make_unique<httplib::Server>()), keyMap({
|
||||
{"A", {HID::Keys::A}},
|
||||
|
@ -99,6 +115,7 @@ void HttpServer::pushAction(std::unique_ptr<HttpAction> action) {
|
|||
}
|
||||
|
||||
void HttpServer::startHttpServer() {
|
||||
server->set_tcp_nodelay(true);
|
||||
server->Get("/ping", [](const httplib::Request&, httplib::Response& response) { response.set_content("pong", "text/plain"); });
|
||||
|
||||
server->Get("/screen", [this](const httplib::Request&, httplib::Response& response) {
|
||||
|
@ -135,9 +152,30 @@ void HttpServer::startHttpServer() {
|
|||
response.set_content(ok ? "ok" : "error", "text/plain");
|
||||
});
|
||||
|
||||
server->Get("/step", [this](const httplib::Request&, httplib::Response& response) {
|
||||
// TODO: implement /step
|
||||
response.set_content("ok", "text/plain");
|
||||
server->Get("/step", [this](const httplib::Request& request, httplib::Response& response) {
|
||||
auto it = request.params.find("frames");
|
||||
if (it == request.params.end()) {
|
||||
response.set_content("error", "text/plain");
|
||||
return;
|
||||
}
|
||||
|
||||
int frames;
|
||||
try {
|
||||
frames = std::stoi(it->second);
|
||||
} catch (...) {
|
||||
response.set_content("error", "text/plain");
|
||||
return;
|
||||
}
|
||||
|
||||
if (frames <= 0) {
|
||||
response.set_content("error", "text/plain");
|
||||
return;
|
||||
}
|
||||
|
||||
DeferredResponseWrapper wrapper(response);
|
||||
std::unique_lock lock(wrapper.mutex);
|
||||
pushAction(HttpAction::createStepAction(wrapper, frames));
|
||||
wrapper.cv.wait(lock, [&wrapper] { return wrapper.ready; });
|
||||
});
|
||||
|
||||
server->Get("/status", [this](const httplib::Request&, httplib::Response& response) { response.set_content(status(), "text/plain"); });
|
||||
|
@ -171,7 +209,6 @@ void HttpServer::startHttpServer() {
|
|||
DeferredResponseWrapper wrapper(response);
|
||||
std::unique_lock lock(wrapper.mutex);
|
||||
pushAction(HttpAction::createLoadRomAction(wrapper, romPath, paused));
|
||||
response.set_content("ok", "text/plain");
|
||||
wrapper.cv.wait(lock, [&wrapper] { return wrapper.ready; });
|
||||
});
|
||||
|
||||
|
@ -209,6 +246,31 @@ std::string HttpServer::status() {
|
|||
void HttpServer::processActions() {
|
||||
std::scoped_lock lock(actionQueueMutex);
|
||||
|
||||
if (framesToRun > 0) {
|
||||
if (!currentStepAction) {
|
||||
// Should never happen
|
||||
printf("framesToRun > 0 but no currentStepAction\n");
|
||||
return;
|
||||
}
|
||||
|
||||
emulator->resume();
|
||||
framesToRun--;
|
||||
|
||||
if (framesToRun == 0) {
|
||||
paused = true;
|
||||
emulator->pause();
|
||||
|
||||
DeferredResponseWrapper& response = reinterpret_cast<HttpActionStep*>(currentStepAction.get())->getResponse();
|
||||
response.inner_response.set_content("ok", "text/plain");
|
||||
std::unique_lock<std::mutex> lock(response.mutex);
|
||||
response.ready = true;
|
||||
response.cv.notify_one();
|
||||
}
|
||||
|
||||
// Don't process more actions until we're done stepping
|
||||
return;
|
||||
}
|
||||
|
||||
HIDService& hid = emulator->kernel.getServiceManager().getHID();
|
||||
|
||||
while (!actionQueue.empty()) {
|
||||
|
@ -253,6 +315,7 @@ void HttpServer::processActions() {
|
|||
|
||||
if (loaded) {
|
||||
paused = loadRomAction->getPaused();
|
||||
framesToRun = 0;
|
||||
if (paused) {
|
||||
emulator->pause();
|
||||
} else {
|
||||
|
@ -263,11 +326,20 @@ void HttpServer::processActions() {
|
|||
}
|
||||
|
||||
case HttpActionType::TogglePause:
|
||||
framesToRun = 0;
|
||||
emulator->togglePause();
|
||||
paused = !paused;
|
||||
break;
|
||||
|
||||
case HttpActionType::Reset: emulator->reset(Emulator::ReloadOption::Reload); break;
|
||||
|
||||
case HttpActionType::Step: {
|
||||
HttpActionStep* stepAction = static_cast<HttpActionStep*>(action.get());
|
||||
framesToRun = stepAction->getFrames();
|
||||
currentStepAction = std::move(action);
|
||||
break;
|
||||
}
|
||||
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue