mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-06-08 03:51:39 +12:00
Add /input command in http server
This commit is contained in:
parent
0949a16e6f
commit
77ea84373f
2 changed files with 87 additions and 5 deletions
|
@ -17,7 +17,7 @@
|
||||||
|
|
||||||
enum class ROMType { None, ELF, NCSD, CXI };
|
enum class ROMType { None, ELF, NCSD, CXI };
|
||||||
|
|
||||||
enum class HttpAction { None, Screenshot };
|
enum class HttpAction { None, Screenshot, PressKey, ReleaseKey };
|
||||||
|
|
||||||
class Emulator {
|
class Emulator {
|
||||||
CPU cpu;
|
CPU cpu;
|
||||||
|
@ -52,6 +52,7 @@ class Emulator {
|
||||||
std::atomic_bool pendingAction = false;
|
std::atomic_bool pendingAction = false;
|
||||||
HttpAction action = HttpAction::None;
|
HttpAction action = HttpAction::None;
|
||||||
std::mutex actionMutex = {};
|
std::mutex actionMutex = {};
|
||||||
|
u32 pendingKey = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Keep the handle for the ROM here to reload when necessary and to prevent deleting it
|
// Keep the handle for the ROM here to reload when necessary and to prevent deleting it
|
||||||
|
|
|
@ -118,6 +118,11 @@ void Emulator::run() {
|
||||||
startHttpServer();
|
startHttpServer();
|
||||||
#endif
|
#endif
|
||||||
while (running) {
|
while (running) {
|
||||||
|
runFrame(); // Run 1 frame of instructions
|
||||||
|
gpu.display(); // Display graphics
|
||||||
|
|
||||||
|
ServiceManager& srv = kernel.getServiceManager();
|
||||||
|
|
||||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(actionMutex);
|
std::scoped_lock lock(actionMutex);
|
||||||
|
@ -127,19 +132,30 @@ void Emulator::run() {
|
||||||
screenshot(httpServerScreenshotPath);
|
screenshot(httpServerScreenshotPath);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case HttpAction::PressKey: {
|
||||||
|
if (pendingKey != 0) {
|
||||||
|
srv.pressKey(pendingKey);
|
||||||
|
pendingKey = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case HttpAction::ReleaseKey: {
|
||||||
|
if (pendingKey != 0) {
|
||||||
|
srv.releaseKey(pendingKey);
|
||||||
|
pendingKey = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case HttpAction::None: {
|
case HttpAction::None: {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
action = HttpAction::None;
|
||||||
pendingAction = false;
|
pendingAction = false;
|
||||||
pendingAction.notify_all();
|
pendingAction.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
runFrame(); // Run 1 frame of instructions
|
|
||||||
gpu.display(); // Display graphics
|
|
||||||
|
|
||||||
ServiceManager& srv = kernel.getServiceManager();
|
|
||||||
|
|
||||||
// Send VBlank interrupts
|
// Send VBlank interrupts
|
||||||
srv.sendGPUInterrupt(GPUInterrupt::VBlank0);
|
srv.sendGPUInterrupt(GPUInterrupt::VBlank0);
|
||||||
|
@ -443,12 +459,42 @@ void Emulator::initGraphicsContext() {
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||||
|
u32 stringToKey(const std::string& key_name) {
|
||||||
|
namespace Keys = HID::Keys;
|
||||||
|
static std::map<std::string, u32> keyMap = {
|
||||||
|
{"A", Keys::A},
|
||||||
|
{"B", Keys::B},
|
||||||
|
{"Select", Keys::Select},
|
||||||
|
{"Start", Keys::Start},
|
||||||
|
{"Right", Keys::Right},
|
||||||
|
{"Left", Keys::Left},
|
||||||
|
{"Up", Keys::Up},
|
||||||
|
{"Down", Keys::Down},
|
||||||
|
{"R", Keys::R},
|
||||||
|
{"L", Keys::L},
|
||||||
|
{"X", Keys::X},
|
||||||
|
{"Y", Keys::Y},
|
||||||
|
{"CirclePadRight", Keys::CirclePadRight},
|
||||||
|
{"CirclePadLeft", Keys::CirclePadLeft},
|
||||||
|
{"CirclePadUp", Keys::CirclePadUp},
|
||||||
|
{"CirclePadDown", Keys::CirclePadDown},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (keyMap.find(key_name) != keyMap.end()) {
|
||||||
|
return keyMap[key_name];
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void Emulator::startHttpServer() {
|
void Emulator::startHttpServer() {
|
||||||
std::thread http_thread([this]() {
|
std::thread http_thread([this]() {
|
||||||
httplib::Server server;
|
httplib::Server server;
|
||||||
|
|
||||||
server.Get("/ping", [](const httplib::Request&, httplib::Response& response) {
|
server.Get("/ping", [](const httplib::Request&, httplib::Response& response) {
|
||||||
response.set_content("pong", "text/plain");
|
response.set_content("pong", "text/plain");
|
||||||
});
|
});
|
||||||
|
|
||||||
server.Get("/screen", [this](const httplib::Request&, httplib::Response& response) {
|
server.Get("/screen", [this](const httplib::Request&, httplib::Response& response) {
|
||||||
{
|
{
|
||||||
std::scoped_lock lock(actionMutex);
|
std::scoped_lock lock(actionMutex);
|
||||||
|
@ -461,6 +507,41 @@ void Emulator::startHttpServer() {
|
||||||
std::vector<char> buffer(std::istreambuf_iterator<char>(image), {});
|
std::vector<char> buffer(std::istreambuf_iterator<char>(image), {});
|
||||||
response.set_content(buffer.data(), buffer.size(), "image/png");
|
response.set_content(buffer.data(), buffer.size(), "image/png");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
server.Get("/input", [this](const httplib::Request& request, httplib::Response& response) {
|
||||||
|
bool ok = false;
|
||||||
|
for (auto& [keyStr, value]: request.params) {
|
||||||
|
auto key = stringToKey(keyStr);
|
||||||
|
printf("Param: %s\n", keyStr.c_str());
|
||||||
|
if (key != 0) {
|
||||||
|
std::scoped_lock lock(actionMutex);
|
||||||
|
pendingAction = true;
|
||||||
|
pendingKey = key;
|
||||||
|
ok = true;
|
||||||
|
if (value == "1") {
|
||||||
|
action = HttpAction::PressKey;
|
||||||
|
} else if (value == "0") {
|
||||||
|
action = HttpAction::ReleaseKey;
|
||||||
|
} else {
|
||||||
|
// Should not happen but just in case
|
||||||
|
pendingAction = false;
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
// Not supporting multiple keys at once for now (ever?)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ok) {
|
||||||
|
response.set_content("ok", "text/plain");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
server.Get("/step", [this](const httplib::Request&, httplib::Response& response) {
|
||||||
|
// TODO: implement /step
|
||||||
|
response.set_content("ok", "text/plain");
|
||||||
|
});
|
||||||
|
|
||||||
// TODO: ability to specify host and port
|
// TODO: ability to specify host and port
|
||||||
printf("Starting HTTP server on port 1234\n");
|
printf("Starting HTTP server on port 1234\n");
|
||||||
server.listen("localhost", 1234);
|
server.listen("localhost", 1234);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue