Files
mitch030504--AstroQuest-Frame/quest-host/cpp/core_process.h
T
bigmak94andClaude Opus 5.5 b5f400bbbd AstroQuest 0.11: ASTRO BOT Rescue Mission in VR on Meta Quest 3 and PC VR
On top of the shadps4-arm64 core imported in the previous commit:

- PlayStation VR emulation: headset, tracker, reprojection, camera and social screen; the
  player's seat and view reset; head velocity for head-butts; field of view settings
- Sound: a native Ngs2 engine (samplers, submixers, effects), the Audio3d spatializer, virtual
  surround for headset speakers, microphone pass-through; libSceJson2; libSceFiber on FEX
- Fixes for CUSA12392 under emulation: real-time step, pace and resolution governor, larger
  render sizes on the PC, save loading at start
- Renderer: geometry shaders fed with fans/polygons/loops, cube-array layers of light probes,
  sample-count mismatches on Adreno, timeline semaphore hang, FXAA in place of the MSAA
  resolve, sharpening, VR frame export
- quest-host: the Quest app (OpenXR host that runs the glibc core as a child process, frames
  through AHardwareBuffers, DualSense mapping, hand-tracked controller placement, KGSL shim)
- PC: in-process OpenXR host (Virtual Desktop or any OpenXR runtime), Touch controllers as the
  gamepad, launcher with a settings window; vendored OpenXR SDK 1.1.63
- Builds keep the build machine's folders out of the binaries (-ffile-prefix-map); machine
  settings (Python, headset serial, signing key) live in git-ignored tools/*.local files
- tools: build, packaging and test scripts for Windows and the headset
- README with installation, license (GPL-2.0-or-later), third-party notices and thanks

No game files are part of the repository; .gitignore only lets listed paths in.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-03 15:00:43 +02:00

148 lines
4.8 KiB
C++

// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include <array>
#include <atomic>
#include <cstdint>
#include <mutex>
#include <optional>
#include <string>
#include <thread>
#include <vector>
#include <sys/types.h>
#include "vr_protocol.h"
/// What the emulated DualShock 4 looks like right now. Buttons use the PS4 pad bit layout.
struct PadState {
uint32_t buttons{};
uint8_t left_x{128}, left_y{128}, right_x{128}, right_y{128};
uint8_t left_trigger{}, right_trigger{};
bool touch_down{};
uint16_t touch_x{}, touch_y{};
bool has_motion{};
float gyro[3]{};
float accel[3]{0.0f, 9.81f, 0.0f};
bool operator==(const PadState&) const = default;
};
/// Whether the game may listen to the headset's microphone, and how much louder than it is
/// what it hears should be made.
struct MicrophoneSettings {
bool enabled{true};
float gain{1.0f};
/// For tests nobody is there to blow for: instead of the microphone, a second of noise
/// every five, as loud as the game takes blowing hard to be.
bool test_signal{};
};
/// Everything needed to start the emulator core.
struct CoreLaunch {
std::string loader; ///< glibc's dynamic loader, inside the app's native library folder
std::string runtime_root; ///< extracted runtime: host/ (libraries, core), drivers/
std::string storage_root; ///< writable folder the core keeps its data in
std::string game; ///< path of the game's eboot.bin
std::string log_file;
std::vector<std::string> extra_args;
std::vector<std::pair<std::string, std::string>> extra_env;
};
/// Runs the emulator core as a child process and serves the sockets it talks to: the control
/// line protocol (state out, controller in), audio, and the VR frame/pose channel.
class CoreProcess {
public:
enum class State { Idle, Starting, Running, Stopped, Failed };
CoreProcess() = default;
~CoreProcess();
bool Start(const CoreLaunch& launch);
void Stop();
State GetState() const {
return state.load();
}
/// Human-readable reason once the state is Stopped or Failed.
std::string GetMessage();
/// Frames the core reported as presented so far.
uint64_t GetPresentedFrames() const {
return presented_frames.load();
}
void SetPad(const PadState& pad);
/// Freezes the emulator while nobody is looking (headset taken off), or lets it go on.
void SetPaused(bool paused);
/// Offers the frame buffers to the core. `fds` are dma-bufs, they stay owned by the caller.
void SetBuffers(const std::vector<int>& fds, uint32_t width, uint32_t height, uint32_t stride);
void SendPose(const Core::Vr::Protocol::Pose& pose);
void SendPadPose(const Core::Vr::Protocol::PadPose& pose);
void SendOptics(float ipd);
/// The display refreshes: the emulated headset keeps step with it (`rate` in Hz).
void SendRefresh(float rate);
/// Returns the newest frame the core finished since the last call, if any.
std::optional<Core::Vr::Protocol::Frame> TakeFrame();
/// What the game last asked of the controller, packed: small motor, large motor, red,
/// green, blue, one byte each from the lowest up.
uint64_t GetPadFeedback() const {
return pad_feedback.load();
}
/// What the emulator process has used: processor time since it started, the processors it
/// may run on (as the system lists them, "0-5") and its memory.
struct Usage {
double cpu_seconds{};
std::string cpus;
int memory_mb{};
};
Usage GetUsage() const;
/// Applies to microphone ports the game opens from now on.
void SetMicrophone(bool enabled, float gain, bool test_signal = false);
/// Thread id of the core's thread whose name starts with `prefix`, or 0.
pid_t FindThread(const std::string& prefix) const;
/// All threads of the emulator whose names begin with `prefix`.
std::vector<pid_t> FindThreads(const std::string& prefix) const;
private:
void ControlLoop();
void AudioLoop();
void VrLoop();
void WaitLoop();
void SendBuffersLocked();
void Fail(const std::string& message);
std::atomic<State> state{State::Idle};
std::atomic<bool> quit{};
std::atomic<bool> paused{};
std::atomic<uint64_t> presented_frames{};
std::atomic<uint64_t> pad_feedback{};
std::atomic<pid_t> pid{-1};
int control_listen{-1};
int audio_listen{-1};
int vr_listen{-1};
std::atomic<int> control_fd{-1};
std::atomic<int> vr_fd{-1};
std::thread control_thread;
std::thread audio_thread;
std::thread vr_thread;
std::thread wait_thread;
MicrophoneSettings microphone;
std::mutex mutex;
std::string message;
PadState pad;
std::optional<Core::Vr::Protocol::Frame> frame;
std::vector<int> buffer_fds;
Core::Vr::Protocol::Buffers buffers{};
bool buffers_sent{};
};