Skip to content

Commit dae56ca

Browse files
committed
Fix button prompts not appearing which fixes shrine exits, dialogues etc
This also fixes a bunch of other visibility checks that the game does! Like enemies etc.
1 parent 7cf6f95 commit dae56ca

File tree

2 files changed

+76
-25
lines changed

2 files changed

+76
-25
lines changed

resources/BreathOfTheWild_BetterVR/patch_FixVisibilityChecks.asm

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,61 @@ moduleMatches = 0x6267BFD0
33

44
.origin = codecave
55

6+
0x03191BA8 = Camera__getAltPerspectiveProjection:
7+
;0x03191BA0 = Camera__getPerspectiveProjection:
8+
69
custom_checkIfCameraCanSeePos:
7-
mflr r0
8-
stw r0, 0x04(r1)
10+
mflr r11
11+
stwu r1, -0x20(r1)
12+
stw r11, 0x24(r1)
13+
stw r3, 0x1C(r1)
14+
stw r5, 0x18(r1)
15+
stw r6, 0x14(r1)
16+
stw r7, 0x10(r1)
17+
stw r8, 0x0C(r1)
18+
19+
mr r8, r0
20+
21+
lis r3, Camera__getPerspectiveProjection@ha
22+
addi r3, r3, Camera__getPerspectiveProjection@l
23+
mtctr r3
24+
lis r3, Camera__sInstance@ha
25+
lwz r3, Camera__sInstance@l(r3)
26+
bctrl
27+
mr r5, r3
28+
29+
lis r3, Camera__getAltPerspectiveProjection@ha
30+
addi r3, r3, Camera__getAltPerspectiveProjection@l
31+
mtctr r3
32+
lis r3, Camera__sInstance@ha
33+
lwz r3, Camera__sInstance@l(r3)
34+
bctrl
35+
mr r6, r3
36+
37+
lwz r3, 0x1C(r1)
38+
; r5 = perspective projection
39+
; r6 = alt perspective projection
40+
lwz r7, 0x24(r1) ; load LR
41+
mr r0, r8 ; restore original r0
942
bla import.coreinit.hook_CheckIfCameraCanSeePos
10-
lwz r0, 0x04(r1)
43+
44+
lwz r8, 0x0C(r1)
45+
lwz r7, 0x10(r1)
46+
lwz r6, 0x14(r1)
47+
lwz r5, 0x18(r1)
48+
;lwz r3, 0x1C(r1) ; r3 should be the return value of CheckIfCameraCanSeePos
49+
lwz r0, 0x24(r1)
50+
addi r1, r1, 0x20
1151
mtlr r0
1252
blr
1353

14-
;0x0318FFA8 = ba custom_checkIfCameraCanSeePos
54+
; fix all visibility checks to use our custom function that will do a query twice for each eye
55+
0x0318FFA8 = li r0, 0
56+
0x0318FFAC = ba custom_checkIfCameraCanSeePos
57+
58+
0x03190118 = li r0, 1
59+
0x0319011C = ba custom_checkIfCameraCanSeePos
60+
1561

1662
; always make AttCheck::ScreenRelated check return true
1763
;0x035D67BC = li r3, 1

src/hooking/camera.cpp

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -592,11 +592,15 @@ std::pair<glm::vec3, glm::fquat> CemuHooks::CalculateVRWorldPose(const BESeadLoo
592592
// in-game camera
593593
glm::mat4x3 viewMatrix = camera.mtx.getLEMatrix();
594594
glm::mat4 worldGame = glm::inverse(glm::mat4(viewMatrix));
595-
glm::vec3 basePos = s_wsCameraPosition;
596-
glm::quat baseRot = s_wsCameraRotation;
597-
auto [swing, baseYaw] = swingTwistY(baseRot);
595+
glm::vec3 basePos = glm::vec3(worldGame[3]);
596+
glm::quat baseRot = glm::quat_cast(worldGame);
597+
598+
// overwrite with our stored camera pos/rot
599+
basePos = s_wsCameraPosition;
600+
baseRot = s_wsCameraRotation;
598601

599-
if (CemuHooks::IsFirstPerson()) {
602+
auto [swing, baseYaw] = swingTwistY(baseRot);
603+
if (IsFirstPerson()) {
600604
// take link's direction, then rotate the headset position
601605
BEMatrix34 playerMtx = {};
602606
readMemory(s_playerMtxAddress, &playerMtx);
@@ -613,7 +617,6 @@ std::pair<glm::vec3, glm::fquat> CemuHooks::CalculateVRWorldPose(const BESeadLoo
613617
}
614618

615619
basePos = playerPos;
616-
617620
if (auto eventSettings = GetFirstPersonSettingsForActiveEvent()) {
618621
if (eventSettings->ignoreCameraRotation) {
619622
glm::fquat playerRot = playerMtx.getRotLE();
@@ -638,12 +641,11 @@ std::pair<glm::vec3, glm::fquat> CemuHooks::CalculateVRWorldPose(const BESeadLoo
638641
return { newPos, newRot };
639642
}
640643

641-
constexpr float VISIBILITY_CHECK_BUFFER = 1.5f;
642644
void CemuHooks::hook_CheckIfCameraCanSeePos(PPCInterpreter_t* hCPU) {
643645
hCPU->instructionPointer = hCPU->sprNew.LR;
644646

645647
if (VRManager::instance().XR->GetRenderer() == nullptr) {
646-
hCPU->gpr[3] = 1;
648+
hCPU->gpr[3] = 0;
647649
return;
648650
}
649651

@@ -656,19 +658,18 @@ void CemuHooks::hook_CheckIfCameraCanSeePos(PPCInterpreter_t* hCPU) {
656658
BESeadLookAtCamera camera = {};
657659
readMemory(camPtr, &camera);
658660

659-
struct {
660-
uint32_t x, y, z;
661-
} posRaw;
662-
readMemory(posPtr, &posRaw);
661+
//uint32_t mainProjectionPtr = hCPU->gpr[5];
662+
//BESeadPerspectiveProjection mainProjection = {};
663+
//readMemory(mainProjectionPtr, &mainProjection);
664+
//uint32_t altProjectionPtr = hCPU->gpr[6];
665+
//BESeadPerspectiveProjection altProjection = {};
666+
//readMemory(altProjectionPtr, &altProjection);
663667

664-
auto swapFloat = [](uint32_t val) -> float {
665-
uint32_t swapped = ((val & 0xFF) << 24) | ((val & 0xFF00) << 8) | ((val & 0xFF0000) >> 8) | ((val & 0xFF000000) >> 24);
666-
float f;
667-
memcpy(&f, &swapped, 4);
668-
return f;
669-
};
668+
//Log::print<INFO>("Main Projection{}: {}", hCPU->gpr[0] == 0 ? " yes " : " no ", mainProjection);
669+
//Log::print<INFO>("Alt Projection{}: {}", hCPU->gpr[0] == 1 ? " yes " : " no ", altProjection);
670670

671-
glm::vec3 center(swapFloat(posRaw.x), swapFloat(posRaw.y), swapFloat(posRaw.z));
671+
BEVec3 center;
672+
readMemory(posPtr, &center);
672673

673674
Frustum frustum;
674675
bool visible = false;
@@ -677,19 +678,23 @@ void CemuHooks::hook_CheckIfCameraCanSeePos(PPCInterpreter_t* hCPU) {
677678
OpenXR::EyeSide side = (i == 0) ? OpenXR::EyeSide::LEFT : OpenXR::EyeSide::RIGHT;
678679
if (auto fovOpt = VRManager::instance().XR->GetRenderer()->GetFOV(side)) {
679680
auto [pos, rot] = CalculateVRWorldPose(camera, side);
681+
682+
// pull the camera backwards a bit to account for it being a third-person game that encompassed a bigger area
683+
pos += rot * glm::vec3(0.0f, 0.0f, 1.0f);
684+
680685
glm::mat4 view = glm::inverse(glm::translate(glm::mat4(1.0f), pos) * glm::mat4_cast(rot));
681-
glm::mat4 proj = calculateProjectionMatrix(nearClip, farClip, fovOpt.value());
686+
glm::mat4 proj = glm::transpose(calculateProjectionMatrix(nearClip, farClip, fovOpt.value()));
682687
glm::mat4 vp = proj * view;
683688

684689
frustum.update(vp);
685-
if (frustum.checkSphere(center, radius+VISIBILITY_CHECK_BUFFER)) {
690+
if (frustum.checkSphere(center.getLE(), radius)) {
686691
visible = true;
687692
break;
688693
}
689694
}
690695
}
691696

692-
Log::print<INFO>("Checking visibility of {} (rad = {}, near = {}, far = {}): {}", center, radius, nearClip, farClip, visible ? "visible" : "invisible");
697+
Log::print<PPC>("Checking visibility of {} (rad = {}, near = {}, far = {}): {}", center, radius, nearClip, farClip, visible ? "visible" : "invisible");
693698

694699
hCPU->gpr[3] = visible ? 1 : 0;
695700
}

0 commit comments

Comments
 (0)