mirror of
https://github.com/mitch030504/AstroQuest-Frame.git
synced 2026-10-24 03:01:23 +02:00
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>
89 lines
4.2 KiB
C++
89 lines
4.2 KiB
C++
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
#pragma once
|
|
|
|
#include <atomic>
|
|
#include <cstdint>
|
|
#include <mutex>
|
|
#include <vector>
|
|
|
|
#include <jni.h>
|
|
|
|
class CoreProcess;
|
|
|
|
/// A picture the Java side draws (text is far easier there) and the headset shows on a floating
|
|
/// panel whenever the game itself has nothing on screen.
|
|
struct StatusImage {
|
|
static constexpr int Width = 1024;
|
|
static constexpr int Height = 512;
|
|
|
|
std::mutex mutex;
|
|
std::vector<uint8_t> pixels; ///< RGBA, top row first
|
|
uint64_t version{};
|
|
};
|
|
|
|
struct XrHostOptions {
|
|
/// Display refresh rate to ask for, 0 keeps the system default.
|
|
float refresh_rate{0.0f};
|
|
/// Size of one eye in the buffers frames are delivered in.
|
|
uint32_t eye_width{1440};
|
|
uint32_t eye_height{1536};
|
|
/// Use the wearer's hands, as the headset sees them around the gamepad, to place the
|
|
/// controller in the game.
|
|
bool track_hands{true};
|
|
/// What the compositor does to the game's picture, which is coarser than the display, on
|
|
/// top of showing it: 0 and 1 nothing (with 1 the emulator sharpens the picture itself,
|
|
/// which is not this struct's business), 2 its Super Resolution filter on every refresh,
|
|
/// 3 the same but only while the system finds the GPU has the time for it, 4 its plainer
|
|
/// and cheaper sharpening filter.
|
|
int sharpen{1};
|
|
/// Have the compositor read the game's picture with a cubic filter instead of a linear
|
|
/// one where it enlarges it: sharper, for a little of the GPU's time on every refresh.
|
|
bool cubic{};
|
|
/// Keep the status panel in view (small, below the middle) while the game runs, for the
|
|
/// figures the app writes on it.
|
|
bool show_stats{};
|
|
/// Ask the system from moment to moment for the size it recommends for the picture. It
|
|
/// counts an app that asks among those that give way when the GPU is short, which is its
|
|
/// condition for the higher GPU clock levels. This app gives way where the GPU's time
|
|
/// goes: in the size the game draws its scene at, which the emulator sees to.
|
|
bool dynamic_resolution{true};
|
|
/// Also show the picture at the recommended size instead of at full size. That saves next
|
|
/// to nothing (the picture is copied once per frame of the game) and blurs what the game
|
|
/// drew; it is what the app did up to version 0.6.
|
|
bool follow_layer_size{};
|
|
/// Ask for the processor's "boost" level: its fastest clock for the first 45 seconds and
|
|
/// for up to a fifth of the time after that, as the system sees fit. That is when the
|
|
/// emulator translates most of the game's code.
|
|
bool cpu_boost{true};
|
|
/// For the probe that runs the host without anybody wearing the headset: ask the session
|
|
/// that never begins for everything that is otherwise asked when it does (refresh rate,
|
|
/// performance levels, thread hints), to have the answers in the log.
|
|
bool probe{};
|
|
/// How far beyond the next display refresh the head pose given to the game is predicted,
|
|
/// in milliseconds. A frame is on the display some tens of milliseconds after the game
|
|
/// read the pose it drew it for; aiming at that moment leaves the compositor less to
|
|
/// correct, which is what shows as black edges when the head turns.
|
|
float predict_ms{25.0f};
|
|
};
|
|
|
|
/// What a request to reset the view asks for (bits of the counter RunXrHost is given).
|
|
namespace XrRecenter {
|
|
/// The way the controller points right now is straight ahead.
|
|
inline constexpr uint32_t Pad = 1;
|
|
/// Where the head is now is where the player sits, and the way it faces is straight ahead.
|
|
inline constexpr uint32_t Seat = 2;
|
|
} // namespace XrRecenter
|
|
|
|
/// What the host worked out about the session, for the status panel and for logging.
|
|
struct XrHostStatus {
|
|
std::atomic<bool> session_running{};
|
|
std::atomic<bool> hands_tracked{};
|
|
std::atomic<float> refresh_rate{};
|
|
};
|
|
|
|
/// Owns the OpenXR session: feeds the head pose to the core and shows the stereo frames it
|
|
/// delivers. Blocks until `quit` is set or the system ends the session.
|
|
void RunXrHost(JavaVM* vm, jobject activity, CoreProcess& core, StatusImage& status,
|
|
const XrHostOptions& options, XrHostStatus& host_status, std::atomic<bool>& quit,
|
|
std::atomic<uint32_t>& recenter_requests);
|