mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 15:45:40 +12:00
Merge remote-tracking branch 'upstream/master' into stencil-logicop-clear
This commit is contained in:
commit
03733569e0
6 changed files with 133 additions and 12 deletions
40
.github/workflows/build_http.yml
vendored
Normal file
40
.github/workflows/build_http.yml
vendored
Normal file
|
@ -0,0 +1,40 @@
|
|||
name: HTTP server build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
# Customize the CMake build type here (Release, Debug, RelWithDebInfo, etc.)
|
||||
BUILD_TYPE: Release
|
||||
|
||||
jobs:
|
||||
build:
|
||||
# The CMake configure and build commands are platform agnostic and should work equally
|
||||
# well on Windows or Mac. You can convert this to a matrix build if you need
|
||||
# cross-platform coverage.
|
||||
# See: https://docs.github.com/en/free-pro-team@latest/actions/learn-github-actions/managing-complex-workflows#using-a-build-matrix
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Fetch submodules
|
||||
run: git submodule update --init --recursive
|
||||
|
||||
- name: Setup Vulkan SDK
|
||||
uses: humbletim/setup-vulkan-sdk@v1.2.0
|
||||
with:
|
||||
vulkan-query-version: latest
|
||||
vulkan-use-cache: true
|
||||
vulkan-components: Vulkan-Headers, Vulkan-Loader, Glslang
|
||||
|
||||
- name: Configure CMake
|
||||
# Configure CMake in a 'build' subdirectory. `CMAKE_BUILD_TYPE` is only required if you are using a single-configuration generator such as make.
|
||||
# See https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html?highlight=cmake_build_type
|
||||
run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ -DENABLE_USER_BUILD=ON -DENABLE_HTTP_SERVER=ON
|
||||
|
||||
- name: Build
|
||||
# Build your program with the given configuration
|
||||
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}
|
|
@ -61,7 +61,7 @@ class Emulator {
|
|||
|
||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||
HttpServer httpServer;
|
||||
friend class HttpServer;
|
||||
friend struct HttpServer;
|
||||
#endif
|
||||
|
||||
// Keep the handle for the ROM here to reload when necessary and to prevent deleting it
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <array>
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
@ -12,12 +13,12 @@
|
|||
|
||||
#include "helpers.hpp"
|
||||
|
||||
enum class HttpActionType { None, Screenshot, Key, TogglePause, Reset };
|
||||
enum class HttpActionType { None, Screenshot, Key, TogglePause, Reset, LoadRom };
|
||||
|
||||
class Emulator;
|
||||
namespace httplib {
|
||||
class Server;
|
||||
class Response;
|
||||
struct Response;
|
||||
}
|
||||
|
||||
// Wrapper for httplib::Response that allows the HTTP server to wait for the response to be ready
|
||||
|
@ -41,7 +42,8 @@ class HttpAction {
|
|||
HttpActionType getType() const { return type; }
|
||||
|
||||
static std::unique_ptr<HttpAction> createScreenshotAction(DeferredResponseWrapper& response);
|
||||
static std::unique_ptr<HttpAction> createKeyAction(uint32_t key, bool state);
|
||||
static std::unique_ptr<HttpAction> createKeyAction(u32 key, bool state);
|
||||
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();
|
||||
};
|
||||
|
|
|
@ -159,8 +159,9 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
|||
|
||||
// Read ExeFS
|
||||
if (hasExeFS()) {
|
||||
u64 exeFSOffset = fileOffset + exeFS.offset; // Offset of ExeFS in the file = exeFS offset + ncch offset
|
||||
printf("ExeFS offset: %08llX, size: %08llX (Offset in file = %08llX)\n", exeFS.offset, exeFS.size, exeFSOffset);
|
||||
// Offset of ExeFS in the file = exeFS offset + NCCH offset
|
||||
// exeFS.offset has already been offset by the NCCH offset
|
||||
printf("ExeFS offset: %08llX, size: %08llX (Offset in file = %08llX)\n", exeFS.offset - info.offset, exeFS.size, exeFS.offset);
|
||||
constexpr size_t exeFSHeaderSize = 0x200;
|
||||
|
||||
u8 exeFSHeader[exeFSHeaderSize];
|
||||
|
|
|
@ -118,6 +118,9 @@ void Emulator::run() {
|
|||
programRunning = true;
|
||||
|
||||
while (programRunning) {
|
||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||
httpServer.processActions();
|
||||
#endif
|
||||
runFrame();
|
||||
HIDService& hid = kernel.getServiceManager().getHID();
|
||||
|
||||
|
@ -367,11 +370,8 @@ void Emulator::togglePause() { running ? pause() : resume(); }
|
|||
|
||||
void Emulator::runFrame() {
|
||||
if (running) {
|
||||
#ifdef PANDA3DS_ENABLE_HTTP_SERVER
|
||||
httpServer.processActions();
|
||||
#endif
|
||||
cpu.runFrame(); // Run 1 frame of instructions
|
||||
gpu.display(); // Display graphics
|
||||
cpu.runFrame(); // Run 1 frame of instructions
|
||||
gpu.display(); // Display graphics
|
||||
|
||||
// Send VBlank interrupts
|
||||
ServiceManager& srv = kernel.getServiceManager();
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
#include <system_error>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
||||
|
@ -40,6 +41,20 @@ class HttpActionKey : public HttpAction {
|
|||
bool getState() const { return state; }
|
||||
};
|
||||
|
||||
class HttpActionLoadRom : public HttpAction {
|
||||
DeferredResponseWrapper& response;
|
||||
const std::filesystem::path& path;
|
||||
bool paused;
|
||||
|
||||
public:
|
||||
HttpActionLoadRom(DeferredResponseWrapper& response, const std::filesystem::path& path, bool paused)
|
||||
: HttpAction(HttpActionType::LoadRom), response(response), path(path), paused(paused) {}
|
||||
|
||||
DeferredResponseWrapper& getResponse() { return response; }
|
||||
const std::filesystem::path& getPath() const { return path; }
|
||||
bool getPaused() const { return paused; }
|
||||
};
|
||||
|
||||
std::unique_ptr<HttpAction> HttpAction::createScreenshotAction(DeferredResponseWrapper& response) {
|
||||
return std::make_unique<HttpActionScreenshot>(response);
|
||||
}
|
||||
|
@ -48,6 +63,10 @@ std::unique_ptr<HttpAction> HttpAction::createKeyAction(u32 key, bool state) { r
|
|||
std::unique_ptr<HttpAction> HttpAction::createTogglePauseAction() { return std::make_unique<HttpActionTogglePause>(); }
|
||||
std::unique_ptr<HttpAction> HttpAction::createResetAction() { return std::make_unique<HttpActionReset>(); }
|
||||
|
||||
std::unique_ptr<HttpAction> HttpAction::createLoadRomAction(DeferredResponseWrapper& response, const std::filesystem::path& path, bool paused) {
|
||||
return std::make_unique<HttpActionLoadRom>(response, path, paused);
|
||||
}
|
||||
|
||||
HttpServer::HttpServer(Emulator* emulator)
|
||||
: emulator(emulator), server(std::make_unique<httplib::Server>()), keyMap({
|
||||
{"A", {HID::Keys::A}},
|
||||
|
@ -83,6 +102,7 @@ void HttpServer::startHttpServer() {
|
|||
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) {
|
||||
// TODO: make the below a DeferredResponseWrapper function
|
||||
DeferredResponseWrapper wrapper(response);
|
||||
// Lock the mutex before pushing the action to ensure that the condition variable is not notified before we wait on it
|
||||
std::unique_lock lock(wrapper.mutex);
|
||||
|
@ -122,6 +142,39 @@ void HttpServer::startHttpServer() {
|
|||
|
||||
server->Get("/status", [this](const httplib::Request&, httplib::Response& response) { response.set_content(status(), "text/plain"); });
|
||||
|
||||
server->Get("/load_rom", [this](const httplib::Request& request, httplib::Response& response) {
|
||||
auto it = request.params.find("path");
|
||||
if (it == request.params.end()) {
|
||||
response.set_content("error", "text/plain");
|
||||
return;
|
||||
}
|
||||
|
||||
std::filesystem::path romPath = it->second;
|
||||
if (romPath.empty()) {
|
||||
response.set_content("error", "text/plain");
|
||||
return;
|
||||
} else {
|
||||
std::error_code error;
|
||||
if (!std::filesystem::is_regular_file(romPath, error)) {
|
||||
std::string message = "error: " + error.message();
|
||||
response.set_content(message, "text/plain");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bool paused = false;
|
||||
it = request.params.find("paused");
|
||||
if (it != request.params.end()) {
|
||||
paused = (it->second == "1");
|
||||
}
|
||||
|
||||
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; });
|
||||
});
|
||||
|
||||
server->Get("/togglepause", [this](const httplib::Request&, httplib::Response& response) {
|
||||
pushAction(HttpAction::createTogglePauseAction());
|
||||
response.set_content("ok", "text/plain");
|
||||
|
@ -187,7 +240,32 @@ void HttpServer::processActions() {
|
|||
break;
|
||||
}
|
||||
|
||||
case HttpActionType::TogglePause: emulator->togglePause(); break;
|
||||
case HttpActionType::LoadRom: {
|
||||
HttpActionLoadRom* loadRomAction = static_cast<HttpActionLoadRom*>(action.get());
|
||||
DeferredResponseWrapper& response = loadRomAction->getResponse();
|
||||
bool loaded = emulator->loadROM(loadRomAction->getPath());
|
||||
|
||||
response.inner_response.set_content(loaded ? "ok" : "error", "text/plain");
|
||||
|
||||
std::unique_lock<std::mutex> lock(response.mutex);
|
||||
response.ready = true;
|
||||
response.cv.notify_one();
|
||||
|
||||
if (loaded) {
|
||||
paused = loadRomAction->getPaused();
|
||||
if (paused) {
|
||||
emulator->pause();
|
||||
} else {
|
||||
emulator->resume();
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case HttpActionType::TogglePause:
|
||||
emulator->togglePause();
|
||||
paused = !paused;
|
||||
break;
|
||||
case HttpActionType::Reset: emulator->reset(Emulator::ReloadOption::Reload); break;
|
||||
|
||||
default: break;
|
||||
|
|
Loading…
Add table
Reference in a new issue