mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
hmd2: initialize a virtual headset with --vr
Inspired by https://github.com/KytyPS5/KytyPS5/pull/607 Co-authored-by: BlackCAT <52720489+psnwd@users.noreply.github.com>
This commit is contained in:
@@ -55,6 +55,10 @@ bool FullscreenEnabled() {
|
|||||||
return g_config->fullscreen_enabled;
|
return g_config->fullscreen_enabled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VrEnabled() {
|
||||||
|
return g_config->vr_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t GetVblankFrequency() {
|
uint32_t GetVblankFrequency() {
|
||||||
return std::clamp(g_config->vblank_frequency, 30u, 360u);
|
return std::clamp(g_config->vblank_frequency, 30u, 360u);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ struct ConfigOptions {
|
|||||||
PresentMode present_mode = PresentMode::Mailbox;
|
PresentMode present_mode = PresentMode::Mailbox;
|
||||||
int32_t gpu_index = -1;
|
int32_t gpu_index = -1;
|
||||||
bool fullscreen_enabled = false;
|
bool fullscreen_enabled = false;
|
||||||
|
bool vr_enabled = false;
|
||||||
uint32_t vblank_frequency = 60;
|
uint32_t vblank_frequency = 60;
|
||||||
uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE;
|
uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE;
|
||||||
bool vulkan_validation_enabled = false;
|
bool vulkan_validation_enabled = false;
|
||||||
@@ -79,6 +80,7 @@ int32_t GetUserId();
|
|||||||
PresentMode GetPresentMode();
|
PresentMode GetPresentMode();
|
||||||
int32_t GetGpuIndex();
|
int32_t GetGpuIndex();
|
||||||
bool FullscreenEnabled();
|
bool FullscreenEnabled();
|
||||||
|
bool VrEnabled();
|
||||||
uint32_t GetVblankFrequency();
|
uint32_t GetVblankFrequency();
|
||||||
uint32_t GetConsoleLanguage();
|
uint32_t GetConsoleLanguage();
|
||||||
bool VulkanValidationEnabled();
|
bool VulkanValidationEnabled();
|
||||||
|
|||||||
@@ -0,0 +1,98 @@
|
|||||||
|
#include "common/emulatorConfig.h"
|
||||||
|
#include "libs/errno.h"
|
||||||
|
#include "libs/libs.h"
|
||||||
|
#include "loader/symbolDatabase.h"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
namespace Libs {
|
||||||
|
|
||||||
|
LIB_VERSION("Hmd2", 1, "Hmd2", 1, 1);
|
||||||
|
|
||||||
|
namespace Hmd2 {
|
||||||
|
|
||||||
|
constexpr int32_t ERROR_ALREADY_INITIALIZED = -1972240383; // 0x8a720001
|
||||||
|
constexpr int32_t ERROR_NOT_INITIALIZED = -1972240382; // 0x8a720002
|
||||||
|
constexpr int32_t ERROR_PARAMETER_NULL = -1972240376; // 0x8a720008
|
||||||
|
|
||||||
|
struct SceHmd2InitializeParam {
|
||||||
|
void* reserved0;
|
||||||
|
uint8_t reserved[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct SceHmd2DeviceInformation {
|
||||||
|
uint32_t status;
|
||||||
|
uint32_t reserve0;
|
||||||
|
struct {
|
||||||
|
struct {
|
||||||
|
uint32_t width;
|
||||||
|
uint32_t height;
|
||||||
|
} panelResolution;
|
||||||
|
struct {
|
||||||
|
uint16_t refreshRate90Hz;
|
||||||
|
uint16_t refreshRate120Hz;
|
||||||
|
} flipToDisplayLatency;
|
||||||
|
} deviceInfo;
|
||||||
|
uint8_t hmuMount;
|
||||||
|
uint8_t lensSeparationDistance;
|
||||||
|
uint8_t reserve1[2];
|
||||||
|
float virtualImageDistance;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sizeof(SceHmd2InitializeParam) == 16);
|
||||||
|
static_assert(offsetof(SceHmd2InitializeParam, reserved) == 8);
|
||||||
|
static_assert(sizeof(SceHmd2DeviceInformation) == 28);
|
||||||
|
static_assert(offsetof(SceHmd2DeviceInformation, deviceInfo) == 8);
|
||||||
|
static_assert(offsetof(SceHmd2DeviceInformation, hmuMount) == 20);
|
||||||
|
static_assert(offsetof(SceHmd2DeviceInformation, virtualImageDistance) == 24);
|
||||||
|
|
||||||
|
static std::atomic<bool> g_initialized = false;
|
||||||
|
|
||||||
|
static int32_t KYTY_SYSV_ABI Hmd2Initialize(const SceHmd2InitializeParam* param) {
|
||||||
|
PRINT_NAME();
|
||||||
|
if (param == nullptr) {
|
||||||
|
return ERROR_PARAMETER_NULL;
|
||||||
|
}
|
||||||
|
if (g_initialized.exchange(true)) {
|
||||||
|
return ERROR_ALREADY_INITIALIZED;
|
||||||
|
}
|
||||||
|
LOGF("Hmd2: initialized, virtual headset=%s\n", Config::VrEnabled() ? "enabled" : "disabled");
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t KYTY_SYSV_ABI Hmd2GetDeviceInformation(SceHmd2DeviceInformation* info) {
|
||||||
|
PRINT_NAME();
|
||||||
|
if (!g_initialized.load()) {
|
||||||
|
return ERROR_NOT_INITIALIZED;
|
||||||
|
}
|
||||||
|
if (info == nullptr) {
|
||||||
|
return ERROR_PARAMETER_NULL;
|
||||||
|
}
|
||||||
|
*info = {};
|
||||||
|
if (Config::VrEnabled()) {
|
||||||
|
// Virtual headset defaults: READY, MOUNT, 63 mm lens separation.
|
||||||
|
info->hmuMount = 1;
|
||||||
|
info->lensSeparationDistance = 63;
|
||||||
|
// Headset characteristics: 4000x2040 panel and 2 m virtual image distance.
|
||||||
|
info->deviceInfo.panelResolution = {4000, 2040};
|
||||||
|
info->virtualImageDistance = 2.0f;
|
||||||
|
// Host presentation has no emulated headset scan-out delay; latency remains zero.
|
||||||
|
} else {
|
||||||
|
info->status = 2; // SCE_HMD2_DEVICE_STATUS_NOT_DETECTED
|
||||||
|
}
|
||||||
|
LOGF("Hmd2: device status=%u panel=%ux%u mounted=%u\n", info->status,
|
||||||
|
info->deviceInfo.panelResolution.width, info->deviceInfo.panelResolution.height,
|
||||||
|
info->hmuMount);
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Hmd2
|
||||||
|
|
||||||
|
LIB_DEFINE(InitHmd2_1) {
|
||||||
|
LIB_FUNC("c812oYs7Vsc", Hmd2::Hmd2Initialize);
|
||||||
|
LIB_FUNC("bIi4YUfSRys", Hmd2::Hmd2GetDeviceInformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Libs
|
||||||
@@ -82,6 +82,7 @@ LIB_DEFINE(InitDialog_1);
|
|||||||
LIB_DEFINE(InitFont_1);
|
LIB_DEFINE(InitFont_1);
|
||||||
LIB_DEFINE(InitFontFt_1);
|
LIB_DEFINE(InitFontFt_1);
|
||||||
LIB_DEFINE(InitAgcDriver_1);
|
LIB_DEFINE(InitAgcDriver_1);
|
||||||
|
LIB_DEFINE(InitHmd2_1);
|
||||||
LIB_DEFINE(InitLibKernel_1);
|
LIB_DEFINE(InitLibKernel_1);
|
||||||
LIB_DEFINE(InitNet_1);
|
LIB_DEFINE(InitNet_1);
|
||||||
LIB_DEFINE(InitPad_1);
|
LIB_DEFINE(InitPad_1);
|
||||||
@@ -115,6 +116,7 @@ void InitAll(Loader::SymbolDatabase* s) {
|
|||||||
InitFont_1(s);
|
InitFont_1(s);
|
||||||
InitFontFt_1(s);
|
InitFontFt_1(s);
|
||||||
InitAgcDriver_1(s);
|
InitAgcDriver_1(s);
|
||||||
|
InitHmd2_1(s);
|
||||||
InitLibKernel_1(s);
|
InitLibKernel_1(s);
|
||||||
LibMouse::InitMouse_1(s);
|
LibMouse::InitMouse_1(s);
|
||||||
LibKeyboard::InitKeyboard_1(s);
|
LibKeyboard::InitKeyboard_1(s);
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ static void PrintUsage() {
|
|||||||
::printf(
|
::printf(
|
||||||
" --gpu <index> Vulkan physical device index. Default: auto.\n");
|
" --gpu <index> Vulkan physical device index. Default: auto.\n");
|
||||||
::printf(" --fullscreen Run in borderless desktop fullscreen.\n");
|
::printf(" --fullscreen Run in borderless desktop fullscreen.\n");
|
||||||
|
::printf(" --vr Enable the virtual VR headset.\n");
|
||||||
::printf(" --vblank-frequency <num> Virtual vblank frequency. Default: 60.\n");
|
::printf(" --vblank-frequency <num> Virtual vblank frequency. Default: 60.\n");
|
||||||
::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n");
|
::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n");
|
||||||
::printf(" --vulkan-validation <true|false> Enable Vulkan validation.\n");
|
::printf(" --vulkan-validation <true|false> Enable Vulkan validation.\n");
|
||||||
@@ -161,6 +162,11 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (arg == "--vr") {
|
||||||
|
options.config.vr_enabled = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (arg == "--playgo-hack") {
|
if (arg == "--playgo-hack") {
|
||||||
options.config.playgo_hack_enabled = true;
|
options.config.playgo_hack_enabled = true;
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
Reference in New Issue
Block a user