Skip to content

Commit 50bf445

Browse files
committed
Add physics-based roomscale support
1 parent 19173b9 commit 50bf445

6 files changed

Lines changed: 440 additions & 114 deletions

File tree

resources/BreathOfTheWild_BetterVR/patch_debug_CTRL_EntityController.asm

Lines changed: 35 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -43,59 +43,42 @@ bctr
4343
; IDA: 0x02D66B58 = mr r4, r29
4444
;0x02D66B58 = bla import.coreinit.hook_TestPlayerSetMtxTeleport
4545

46-
RoomscaleDelta = 0x20
47-
RoomscaleStep = 0x30
48-
RoomscaleCurrent = 0x40
49-
RoomscaleHit = 0x50
50-
RoomscaleLayerMask = 0x60
51-
RoomscaleSavedLR = 0x64
52-
RoomscaleQuery = 0x70
53-
54-
const_roomscaleQuarter:
55-
.float 0.25
46+
RoomscaleScratch = 0x20
47+
RoomscaleCurrent = RoomscaleScratch + 0x00
48+
RoomscaleCastFrom = RoomscaleScratch + 0x0C
49+
RoomscaleCastDelta = RoomscaleScratch + 0x18
50+
RoomscaleHit = RoomscaleScratch + 0x24
51+
RoomscaleLayerMask = RoomscaleScratch + 0x30
52+
RoomscaleSavedLR = 0x58
53+
RoomscaleQuery = 0x60
5654

5755
ApplyRoomscaleAfterPlayerVelocity:
58-
stwu r1, -0x120(r1)
56+
stwu r1, -0x110(r1)
5957
mflr r0
60-
stw r0, 0x124(r1)
58+
stw r0, 0x114(r1)
6159
stw r30, 0x14(r1)
6260
stw r31, 0x18(r1)
6361

6462
mr r3, r31
65-
addi r4, r1, RoomscaleDelta
66-
bla import.coreinit.hook_GetRoomscaleDelta
63+
addi r4, r1, RoomscaleScratch
64+
bla import.coreinit.hook_BeginRoomscaleMovement
6765
lwz r31, 0x18(r1)
6866

6967
cmpwi r3, 0
7068
beq ApplyRoomscaleAfterPlayerVelocity_Continue
7169

72-
lis r12, const_roomscaleQuarter@ha
73-
lfs f0, const_roomscaleQuarter@l(r12)
74-
75-
lfs f1, RoomscaleDelta + 0x0(r1)
76-
fmuls f1, f1, f0
77-
stfs f1, RoomscaleStep + 0x0(r1)
78-
79-
lfs f1, RoomscaleDelta + 0x4(r1)
80-
fmuls f1, f1, f0
81-
stfs f1, RoomscaleStep + 0x4(r1)
82-
83-
lfs f1, RoomscaleDelta + 0x8(r1)
84-
fmuls f1, f1, f0
85-
stfs f1, RoomscaleStep + 0x8(r1)
86-
8770
mr r3, r31
8871
addi r4, r1, RoomscaleCurrent
8972
bl RigidBody_getPosition
9073

91-
li r30, 4
92-
9374
ApplyRoomscaleAfterPlayerVelocity_Loop:
94-
cmpwi r30, 0
75+
addi r3, r1, RoomscaleScratch
76+
bla import.coreinit.hook_PrepareRoomscaleRaycast
77+
lwz r31, 0x18(r1)
78+
cmpwi r3, 2
9579
beq ApplyRoomscaleAfterPlayerVelocity_Warp
96-
97-
li r0, 15
98-
stw r0, RoomscaleLayerMask(r1)
80+
cmpwi r3, 1
81+
bne ApplyRoomscaleAfterPlayerVelocity_Continue
9982

10083
addi r3, r1, RoomscaleQuery
10184
li r4, 0
@@ -107,54 +90,35 @@ addi r4, r31, 0x208
10790
bl RayCast_setLayers
10891

10992
addi r3, r1, RoomscaleQuery
110-
addi r4, r1, RoomscaleCurrent
111-
addi r5, r1, RoomscaleStep
93+
addi r4, r1, RoomscaleCastFrom
94+
addi r5, r1, RoomscaleCastDelta
11295
bl RayCast_setFromAndDelta
11396

11497
addi r3, r1, RoomscaleQuery
11598
li r4, 0
11699
bl RayCastBodyQuery_worldRayCast
117-
cmpwi r3, 0
118-
beq ApplyRoomscaleAfterPlayerVelocity_NoHit
100+
mr r30, r3
101+
cmpwi r30, 0
102+
beq ApplyRoomscaleAfterPlayerVelocity_Consume
119103

120104
addi r3, r1, RoomscaleQuery
121105
addi r4, r1, RoomscaleHit
122106
bl RayCast_getHitPosition
123107

108+
ApplyRoomscaleAfterPlayerVelocity_Consume:
124109
addi r3, r1, RoomscaleQuery
125110
li r4, 2
126111
bl RayCastBodyQuery_dtor
127112

128-
lfs f0, RoomscaleHit + 0x0(r1)
129-
stfs f0, RoomscaleCurrent + 0x0(r1)
130-
lfs f0, RoomscaleHit + 0x4(r1)
131-
stfs f0, RoomscaleCurrent + 0x4(r1)
132-
lfs f0, RoomscaleHit + 0x8(r1)
133-
stfs f0, RoomscaleCurrent + 0x8(r1)
134-
b ApplyRoomscaleAfterPlayerVelocity_Warp
135-
136-
ApplyRoomscaleAfterPlayerVelocity_NoHit:
137-
addi r3, r1, RoomscaleQuery
138-
li r4, 2
139-
bl RayCastBodyQuery_dtor
140-
141-
lfs f0, RoomscaleCurrent + 0x0(r1)
142-
lfs f1, RoomscaleStep + 0x0(r1)
143-
fadds f0, f0, f1
144-
stfs f0, RoomscaleCurrent + 0x0(r1)
145-
146-
lfs f0, RoomscaleCurrent + 0x4(r1)
147-
lfs f1, RoomscaleStep + 0x4(r1)
148-
fadds f0, f0, f1
149-
stfs f0, RoomscaleCurrent + 0x4(r1)
150-
151-
lfs f0, RoomscaleCurrent + 0x8(r1)
152-
lfs f1, RoomscaleStep + 0x8(r1)
153-
fadds f0, f0, f1
154-
stfs f0, RoomscaleCurrent + 0x8(r1)
155-
156-
addi r30, r30, -1
157-
b ApplyRoomscaleAfterPlayerVelocity_Loop
113+
addi r3, r1, RoomscaleScratch
114+
mr r4, r30
115+
bla import.coreinit.hook_ConsumeRoomscaleRaycast
116+
lwz r31, 0x18(r1)
117+
cmpwi r3, 2
118+
beq ApplyRoomscaleAfterPlayerVelocity_Warp
119+
cmpwi r3, 1
120+
beq ApplyRoomscaleAfterPlayerVelocity_Loop
121+
b ApplyRoomscaleAfterPlayerVelocity_Continue
158122

159123
ApplyRoomscaleAfterPlayerVelocity_Warp:
160124
lwz r11, 0xE8(r31)
@@ -198,8 +162,8 @@ bl SyncPhysicsFieldAfterSetPosition
198162
ApplyRoomscaleAfterPlayerVelocity_Continue:
199163
lwz r31, 0x18(r1)
200164
lwz r30, 0x14(r1)
201-
lwz r0, 0x124(r1)
202-
addi r1, r1, 0x120
165+
lwz r0, 0x114(r1)
166+
addi r1, r1, 0x110
203167
mtlr r0
204168
lwz r3, 0x4(r31)
205169
lis r12, ContinueAfterApplyRoomscaleAfterPlayerVelocity@ha

src/hooking/camera.cpp

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,24 @@ bool s_wasCrouching = false;
8585
float actualCrouchOffset = 0.0f;
8686
std::chrono::steady_clock::time_point crouch_state_change_time;
8787

88+
static glm::fvec3 GetAppliedHeadsetOffset(glm::fvec3 eyePos) {
89+
if (CemuHooks::IsFirstPerson()) {
90+
glm::fvec3 appliedHeadPos = CemuHooks::GetAppliedRoomscaleHeadPosition();
91+
eyePos.x -= appliedHeadPos.x;
92+
eyePos.z -= appliedHeadPos.z;
93+
}
94+
return eyePos;
95+
}
96+
97+
static glm::mat4 GetAppliedHeadsetPose(glm::mat4 pose) {
98+
if (CemuHooks::IsFirstPerson()) {
99+
glm::fvec3 appliedHeadPos = CemuHooks::GetAppliedRoomscaleHeadPosition();
100+
pose[3].x -= appliedHeadPos.x;
101+
pose[3].z -= appliedHeadPos.z;
102+
}
103+
return pose;
104+
}
105+
88106
void CemuHooks::hook_UpdateCameraForGameplay(PPCInterpreter_t* hCPU) {
89107
hCPU->instructionPointer = hCPU->sprNew.LR;
90108

@@ -200,7 +218,7 @@ void CemuHooks::hook_UpdateCameraForGameplay(PPCInterpreter_t* hCPU) {
200218
Log::print<ERROR>("hook_UpdateCameraForGameplay: No views available for the middle pose.");
201219
return;
202220
}
203-
auto& views = viewsOpt.value();
221+
glm::mat4 views = GetAppliedHeadsetPose(viewsOpt.value());
204222

205223
// calculate final camera matrix
206224
glm::mat4 finalPose = glm::inverse(existingGameMtx) * views;
@@ -317,7 +335,7 @@ void CemuHooks::hook_GetRenderCamera(PPCInterpreter_t* hCPU) {
317335
std::optional<XrPosef> currPoseOpt = VRManager::instance().XR->GetRenderer()->GetPose(side);
318336
if (!currPoseOpt.has_value())
319337
return;
320-
glm::fvec3 eyePos = ToGLM(currPoseOpt.value().position);
338+
glm::fvec3 eyePos = GetAppliedHeadsetOffset(ToGLM(currPoseOpt.value().position));
321339
glm::fquat eyeRot = ToGLM(currPoseOpt.value().orientation);
322340

323341
glm::vec3 newPos = basePos + (baseYaw * eyePos);
@@ -542,7 +560,7 @@ void CemuHooks::hook_ModifyProjectionUsingCamera(PPCInterpreter_t* hCPU) {
542560
std::optional<XrPosef> currPoseOpt = VRManager::instance().XR->GetRenderer()->GetPose(side);
543561
if (!currPoseOpt.has_value())
544562
return;
545-
glm::fvec3 eyePos = ToGLM(currPoseOpt.value().position);
563+
glm::fvec3 eyePos = GetAppliedHeadsetOffset(ToGLM(currPoseOpt.value().position));
546564
glm::fquat eyeRot = ToGLM(currPoseOpt.value().orientation);
547565

548566
glm::vec3 newPos = basePos + (baseYaw * eyePos);
@@ -646,7 +664,7 @@ std::pair<glm::vec3, glm::fquat> CemuHooks::CalculateVRWorldPose(const BESeadLoo
646664
return { basePos, baseRot };
647665
}
648666

649-
glm::fvec3 eyePos = ToGLM(currPoseOpt.value().position);
667+
glm::fvec3 eyePos = GetAppliedHeadsetOffset(ToGLM(currPoseOpt.value().position));
650668
glm::fquat eyeRot = ToGLM(currPoseOpt.value().orientation);
651669

652670
glm::vec3 newPos = basePos + (baseYaw * eyePos);

src/hooking/cemu_hooks.h

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,14 @@ class CemuHooks {
2828
osLib_registerHLEFunction("coreinit", "hook_CreateNewActor", &hook_CreateNewActor);
2929

3030
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyVelocity", &hook_SetRigidBodyVelocity);
31+
osLib_registerHLEFunction("coreinit", "hook_GetRoomscaleDelta", &hook_GetRoomscaleDelta);
32+
osLib_registerHLEFunction("coreinit", "hook_BeginRoomscaleMovement", &hook_BeginRoomscaleMovement);
33+
osLib_registerHLEFunction("coreinit", "hook_PrepareRoomscaleRaycast", &hook_PrepareRoomscaleRaycast);
34+
osLib_registerHLEFunction("coreinit", "hook_ConsumeRoomscaleRaycast", &hook_ConsumeRoomscaleRaycast);
3135
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyTransform", &hook_SetRigidBodyTransform);
36+
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyScale", &hook_SetRigidBodyScale);
3237
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyPosition", &hook_SetRigidBodyPosition);
3338
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyPositionAndRotation", &hook_SetRigidBodyPositionAndRotation);
34-
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyRotation", &hook_SetRigidBodyRotation);
3539

3640
// Stereo Rendering/Camera Hooks
3741
osLib_registerHLEFunction("coreinit", "hook_BeginCameraSide", &hook_BeginCameraSide);
@@ -137,6 +141,8 @@ class CemuHooks {
137141
static bool IsScreenOpen(ScreenId screen);
138142
static bool IsScreenVisible(ScreenId screen);
139143
static bool IsAnyFadeScreenVisible();
144+
static glm::fvec3 GetAppliedRoomscaleHeadPosition();
145+
static float GetRoomscaleFadeAmount();
140146

141147
static void DrawDebugOverlays();
142148

@@ -171,10 +177,14 @@ class CemuHooks {
171177
static void hook_CreateNewActor(PPCInterpreter_t* hCPU);
172178

173179
static void hook_SetRigidBodyVelocity(PPCInterpreter_t* hCPU);
180+
static void hook_GetRoomscaleDelta(PPCInterpreter_t* hCPU);
181+
static void hook_BeginRoomscaleMovement(PPCInterpreter_t* hCPU);
182+
static void hook_PrepareRoomscaleRaycast(PPCInterpreter_t* hCPU);
183+
static void hook_ConsumeRoomscaleRaycast(PPCInterpreter_t* hCPU);
174184
static void hook_SetRigidBodyTransform(PPCInterpreter_t* hCPU);
185+
static void hook_SetRigidBodyScale(PPCInterpreter_t* hCPU);
175186
static void hook_SetRigidBodyPosition(PPCInterpreter_t* hCPU);
176187
static void hook_SetRigidBodyPositionAndRotation(PPCInterpreter_t* hCPU);
177-
static void hook_SetRigidBodyRotation(PPCInterpreter_t* hCPU);
178188

179189
// Camera Hooks
180190
static void hook_BeginCameraSide(PPCInterpreter_t* hCPU);

0 commit comments

Comments
 (0)