Skip to content

Commit 3d1b180

Browse files
committed
Add entity controller code for future features
Was working on fixing the arrow aim, but didn't quite work.
1 parent a3982e0 commit 3d1b180

File tree

6 files changed

+236
-34
lines changed

6 files changed

+236
-34
lines changed

CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ target_sources(BetterVR_Layer PUBLIC
8787
${CMAKE_CURRENT_SOURCE_DIR}/src/hooking/rumble.h
8888
${CMAKE_CURRENT_SOURCE_DIR}/src/hooking/skeleton.cpp
8989
${CMAKE_CURRENT_SOURCE_DIR}/src/hooking/openxr_motion_bridge.h
90+
${CMAKE_CURRENT_SOURCE_DIR}/src/hooking/entity_controller.cpp
9091
${CMAKE_CURRENT_SOURCE_DIR}/src/rendering/d3d12.cpp
9192
${CMAKE_CURRENT_SOURCE_DIR}/src/rendering/d3d12.h
9293
${CMAKE_CURRENT_SOURCE_DIR}/src/rendering/renderer.cpp
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
[BetterVR_EntityController_V208]
2+
moduleMatches = 0x6267BFD0
3+
4+
.origin = codecave
5+
6+
; hooks entity transform and velocity updates
7+
0x0348970C = ba import.coreinit.hook_SetRigidBodyVelocity
8+
0x03486CD4 = ba import.coreinit.hook_SetRigidBodyTransform
9+
0x03486D80 = ba import.coreinit.hook_SetRigidBodyPosition
10+
0x03489A80 = ba import.coreinit.hook_SetRigidBodyPositionAndRotation
11+
0x0348AB20 = ba import.coreinit.hook_SetRigidBodyRotation
12+
13+
14+
; hooks arrow shooting parameters (and other dynamically loaded bools/values inside AI Actions)
15+
0x030EC840 = ba import.coreinit.hook_LoadDynamicVec3
16+
0x030EC8C0 = bla import.coreinit.hook_LoadDynamicBool
17+
18+
0x1011A7A0 = str_IsShootByPlayer:
19+
0x1011A7F4 = str_TargetPos:
20+
0x030EC860 = ksys__act__ai__InlineParamPack__addBool:
21+
0x030EC7DC = ksys__act__ai__InlineParamPack__addVec3:
22+
23+
; swap TargetPos and IsShootByPlayer to be able to mutate the TargetPos value AFTER we know that the arrow is shot by the player
24+
25+
; .origin = 0x02705AFC
26+
;
27+
; lis r6, str_IsShootByPlayer@ha
28+
; addi r6, r6, str_IsShootByPlayer@l
29+
; lwz r5, 0x0E8(r29)
30+
; stw r27, 0x014(r1)
31+
; stw r6, 0x010(r1)
32+
; lwz r8, 0x4EC(r5)
33+
; mtctr r8
34+
; mr r3, r29
35+
; bctrl
36+
; mr r4, r3
37+
; li r6, -1
38+
; addi r5, r1, 0x010
39+
; addi r3, r1, 0x158
40+
; bl ksys__act__ai__InlineParamPack__addBool
41+
;
42+
; lis r4, str_TargetPos@ha
43+
; addi r4, r4, str_TargetPos@l
44+
; li r6, -1
45+
; addi r5, r1, 0x010
46+
; stw r4, 0x010(r1)
47+
; addi r4, r1, 0x88
48+
; addi r3, r1, 0x158
49+
; stw r27, 0x14(r1)
50+
; bl ksys__act__ai__InlineParamPack__addVec3
51+
;
52+
; .origin = codecave

src/hooking/camera.cpp

Lines changed: 1 addition & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ void CemuHooks::hook_GetRenderCamera(PPCInterpreter_t* hCPU) {
278278
hCPU->instructionPointer = hCPU->sprNew.LR;
279279
uint32_t cameraIn = hCPU->gpr[3];
280280
uint32_t cameraOut = hCPU->gpr[12];
281-
OpenXR::EyeSide side = hCPU->gpr[11] == 0 ? OpenXR::EyeSide::LEFT : OpenXR::EyeSide::RIGHT;
281+
EyeSide side = hCPU->gpr[11] == 0 ? EyeSide::LEFT : EyeSide::RIGHT;
282282

283283
if (UseBlackBarsDuringEvents()) {
284284
return;
@@ -708,16 +708,6 @@ void CemuHooks::hook_CheckIfCameraCanSeePos(PPCInterpreter_t* hCPU) {
708708
BESeadLookAtCamera camera = {};
709709
readMemory(camPtr, &camera);
710710

711-
//uint32_t mainProjectionPtr = hCPU->gpr[5];
712-
//BESeadPerspectiveProjection mainProjection = {};
713-
//readMemory(mainProjectionPtr, &mainProjection);
714-
//uint32_t altProjectionPtr = hCPU->gpr[6];
715-
//BESeadPerspectiveProjection altProjection = {};
716-
//readMemory(altProjectionPtr, &altProjection);
717-
718-
//Log::print<INFO>("Main Projection{}: {}", hCPU->gpr[0] == 0 ? " yes " : " no ", mainProjection);
719-
//Log::print<INFO>("Alt Projection{}: {}", hCPU->gpr[0] == 1 ? " yes " : " no ", altProjection);
720-
721711
BEVec3 center;
722712
readMemory(posPtr, &center);
723713

@@ -1125,25 +1115,3 @@ void CemuHooks::hook_VisualizeRayCastHits(PPCInterpreter_t* hCPU) {
11251115
DebugDraw::instance().Line(rayStart, raycastHitPos, IM_COL32(255, 0, 255, 255));
11261116
DebugDraw::instance().Line(raycastHitPos, rayEnd, IM_COL32(128, 0, 128, 128));
11271117
}
1128-
1129-
// turns out this only does the minimap ui, and not the stamina UI :/
1130-
//void CemuHooks::hook_UpdateUIPosition(PPCInterpreter_t* hCPU) {
1131-
// hCPU->instructionPointer = hCPU->sprNew.LR;
1132-
//
1133-
// EyeSide side = hCPU->gpr[10] == 0 ? EyeSide::LEFT : EyeSide::RIGHT;
1134-
// uint32_t currFrameCounter = hCPU->gpr[11];
1135-
// uint32_t doesUIManagerExist = hCPU->gpr[3] != 0;
1136-
// uint32_t uiManagerInstance = hCPU->gpr[12];
1137-
//
1138-
// if (!doesUIManagerExist) {
1139-
// return;
1140-
// }
1141-
//
1142-
// BEVec3 playerPosCopy = getMemory<BEVec3>(uiManagerInstance + offsetof(UIManager, innerArray.uiPos1));
1143-
// BEVec3 playerMtxPositionCopy = getMemory<BEVec3>(uiManagerInstance + offsetof(UIManager, innerArray.uiPos2));
1144-
//
1145-
// Log::print<INFO>("[{}] Updating UI position (frame = {}, playerPos = {}, playerMtxPos = {})", side, currFrameCounter, playerPosCopy, playerMtxPositionCopy);
1146-
//
1147-
// writeMemory(uiManagerInstance + offsetof(UIManager, innerArray.uiPos1), &playerPosCopy);
1148-
// writeMemory(uiManagerInstance + offsetof(UIManager, innerArray.uiPos2), &playerMtxPositionCopy);
1149-
//}

src/hooking/cemu_hooks.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ class CemuHooks {
2727
osLib_registerHLEFunction("coreinit", "hook_UpdateActorList", &hook_UpdateActorList);
2828
osLib_registerHLEFunction("coreinit", "hook_CreateNewActor", &hook_CreateNewActor);
2929

30+
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyVelocity", &hook_SetRigidBodyVelocity);
31+
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyTransform", &hook_SetRigidBodyTransform);
32+
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyPosition", &hook_SetRigidBodyPosition);
33+
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyPositionAndRotation", &hook_SetRigidBodyPositionAndRotation);
34+
osLib_registerHLEFunction("coreinit", "hook_SetRigidBodyRotation", &hook_SetRigidBodyRotation);
35+
3036
// Stereo Rendering/Camera Hooks
3137
osLib_registerHLEFunction("coreinit", "hook_BeginCameraSide", &hook_BeginCameraSide);
3238
osLib_registerHLEFunction("coreinit", "hook_ModifyLightPrePassProjectionMatrix", &hook_ModifyLightPrePassProjectionMatrix);
@@ -77,6 +83,8 @@ class CemuHooks {
7783
osLib_registerHLEFunction("coreinit", "hook_FixUIBlending", &hook_FixUIBlending);
7884
osLib_registerHLEFunction("coreinit", "hook_FixCameraSaveFilesAndInventory", &hook_FixCameraSaveFilesAndInventory);
7985
osLib_registerHLEFunction("coreinit", "hook_VisualizeRayCastHits", &hook_VisualizeRayCastHits);
86+
osLib_registerHLEFunction("coreinit", "hook_LoadDynamicVec3", &hook_LoadDynamicVec3);
87+
osLib_registerHLEFunction("coreinit", "hook_LoadDynamicBool", &hook_LoadDynamicBool);
8088
};
8189
~CemuHooks() {
8290
FreeLibrary(m_cemuHandle);
@@ -224,6 +232,12 @@ class CemuHooks {
224232
static void hook_UpdateActorList(PPCInterpreter_t* hCPU);
225233
static void hook_CreateNewActor(PPCInterpreter_t* hCPU);
226234

235+
static void hook_SetRigidBodyVelocity(PPCInterpreter_t* hCPU);
236+
static void hook_SetRigidBodyTransform(PPCInterpreter_t* hCPU);
237+
static void hook_SetRigidBodyPosition(PPCInterpreter_t* hCPU);
238+
static void hook_SetRigidBodyPositionAndRotation(PPCInterpreter_t* hCPU);
239+
static void hook_SetRigidBodyRotation(PPCInterpreter_t* hCPU);
240+
227241
// Camera Hooks
228242
static void hook_BeginCameraSide(PPCInterpreter_t* hCPU);
229243
static void hook_ModifyLightPrePassProjectionMatrix(PPCInterpreter_t* hCPU);
@@ -274,6 +288,8 @@ class CemuHooks {
274288
static void hook_CreateNewScreen(PPCInterpreter_t* hCPU);
275289
static void hook_FixUIBlending(PPCInterpreter_t* hCPU);
276290
static void hook_FixCameraSaveFilesAndInventory(PPCInterpreter_t* hCPU);
291+
static void hook_LoadDynamicVec3(PPCInterpreter_t* hCPU);
292+
static void hook_LoadDynamicBool(PPCInterpreter_t* hCPU);
277293

278294
public:
279295
template <typename T>

src/hooking/entity_controller.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
#include "cemu_hooks.h"
2+
3+
bool shouldAdjustArrowTarget = false;
4+
5+
void CemuHooks::hook_LoadDynamicBool(PPCInterpreter_t* hCPU) {
6+
hCPU->instructionPointer = hCPU->sprNew.LR;
7+
hCPU->sprNew.LR = hCPU->gpr[0];
8+
9+
InlineParamBool boolParam;
10+
readMemory(hCPU->gpr[30], &boolParam);
11+
12+
const char* paramString = (char*)(boolParam.keyPtr.getLE() + s_memoryBaseAddress);
13+
Log::print<PPC>("[{:08X}] Loaded dynamic bool parameter for {}: {}", hCPU->gpr[0], paramString, boolParam.value.getLE());
14+
15+
if (std::string(paramString) == "IsShootByPlayer" && boolParam.value.getLE() == 1) {
16+
Log::print<PPC>("Arrow is being shot by the player!");
17+
shouldAdjustArrowTarget = true;
18+
}
19+
}
20+
21+
void CemuHooks::hook_LoadDynamicVec3(PPCInterpreter_t* hCPU) {
22+
hCPU->instructionPointer = 0x030EC844;
23+
24+
InlineParamVec3 vec3Param;
25+
readMemory(hCPU->gpr[31], &vec3Param);
26+
27+
// get LR from stack, using lwz r0, 0x1C(r1)
28+
BEType<uint32_t> addr;
29+
readMemory(hCPU->gpr[1] + 0x1C, &addr);
30+
31+
// we overwrote the .z setting instruction with the jump, so run the original code
32+
vec3Param.value.z = hCPU->fpr[0].fp0;
33+
writeMemory(hCPU->gpr[31], &vec3Param);
34+
35+
//// now hook the value if needed
36+
//const char* paramString = (char*)(vec3Param.keyPtr.getLE() + s_memoryBaseAddress);
37+
//Log::print<PPC>("[{:08X}] Original velocity parameter for {}: {}", addr.getLE(), paramString, vec3Param.value);
38+
39+
// only hook the arrow target position for now
40+
//if (std::string(paramString) == "TargetPos" && shouldAdjustArrowTarget) {
41+
// //Log::print<INFO>("Original target: {}", vec3Param.value.getLE());
42+
// s_lastScreenAimOriginalTarget = vec3Param.value.getLE();
43+
// s_lastScreenAimValid = false;
44+
//}
45+
46+
//velocityParam.value = glm::fvec3(0.0f, 0.0f, 0.0f);
47+
}
48+
49+
void CemuHooks::hook_SetRigidBodyVelocity(PPCInterpreter_t* hCPU) {
50+
hCPU->instructionPointer = 0x03489710;
51+
hCPU->gpr[0] = hCPU->sprNew.LR;
52+
uint32_t lr = hCPU->sprNew.LR;
53+
54+
//uint32_t rigidBodyAddr = hCPU->gpr[3];
55+
//BEVec3 velocity;
56+
//readMemory(hCPU->gpr[4], &velocity);
57+
//double timeDeltaMaybe = hCPU->fpr[1].fp0;
58+
59+
//float debugLineLength = glm::max(s_lastScreenAimDistance, 10.0f);
60+
//if (s_lastGameplayAimValid) {
61+
// DebugDraw::instance().Line(s_lastGameplayAimOrigin, s_lastGameplayAimOrigin + (s_lastGameplayAimDirection * debugLineLength), IM_COL32(0, 255, 255, 255), 2.0f);
62+
//}
63+
//if (s_lastRenderAimValid) {
64+
// DebugDraw::instance().Line(s_lastRenderAimOrigin, s_lastRenderAimOrigin + (s_lastRenderAimDirection * debugLineLength), IM_COL32(255, 0, 255, 255), 2.0f);
65+
//}
66+
//if (s_lastScreenAimValid) {
67+
// DebugDraw::instance().Line(s_lastScreenAimOrigin, s_lastScreenAimAdjustedTarget, IM_COL32(255, 255, 0, 255), 2.0f);
68+
// DebugDraw::instance().Line(s_lastScreenAimOriginalTarget, s_lastScreenAimOriginalTarget + glm::fvec3(0.0f, 0.5f, 0.0f), IM_COL32(255, 64, 64, 255), 1.0f);
69+
// DebugDraw::instance().Line(s_lastScreenAimAdjustedTarget, s_lastScreenAimAdjustedTarget + glm::fvec3(0.0f, 0.5f, 0.0f), IM_COL32(64, 255, 64, 255), 1.0f);
70+
//}
71+
//
72+
73+
//if (lr == 0x020E735C) {
74+
// Log::print<PPC>("[{:08X}] Set rigid body velocity of {:08X}: {} (timeDeltaMaybe = {})", hCPU->sprNew.LR, rigidBodyAddr, velocity, timeDeltaMaybe);
75+
// //velocity = glm::fvec3(0.0f, 0.0f, 0.0f);
76+
// //velocity.x = 0.0f;
77+
// writeMemory(hCPU->gpr[4], &velocity);
78+
//}
79+
}
80+
81+
void CemuHooks::hook_SetRigidBodyTransform(PPCInterpreter_t* hCPU) {
82+
hCPU->instructionPointer = 0x03486CD8;
83+
hCPU->gpr[0] = hCPU->sprNew.LR;
84+
uint32_t lr = hCPU->sprNew.LR;
85+
86+
//uint32_t rigidBodyAddr = hCPU->gpr[3];
87+
//BEMatrix34 transform;
88+
//readMemory(hCPU->gpr[4], &transform);
89+
90+
//DebugDraw::instance().Dot(transform.getPos().getLE(), 5.0f, IM_COL32(0, 0, 255, 255));
91+
//
92+
//Log::print<INFO>("[{:08X}] Set rigid body transform of {:08X}: pos = {}, rot = {}", lr, rigidBodyAddr, transform.getPos().getLE(), transform.getRotLE());
93+
94+
//if (lr == 0x020E3D0C || lr == 0x02C19A18) {
95+
// shouldAdjustArrowTarget = false;
96+
97+
// glm::fvec3 originalPos = transform.getPos().getLE();
98+
// glm::fquat originalRot = transform.getRotLE();
99+
// Log::print<INFO>("[ARROW TRANSFORM] Original pos = {}, rot = {}", originalPos, originalRot);
100+
101+
// auto renderer = VRManager::instance().XR->GetRenderer();
102+
// if (renderer != nullptr) {
103+
// auto rightPoseOpt = renderer->GetPose(EyeSide::RIGHT);
104+
// if (rightPoseOpt.has_value()) {
105+
// glm::fvec3 headsetPos = ToGLM(rightPoseOpt->position);
106+
// glm::fquat headsetRot = ToGLM(rightPoseOpt->orientation);
107+
108+
// auto [swing, baseYaw] = swingTwistY(s_wsCameraRotation);
109+
// glm::fvec3 headsetPosNoHeight = headsetPos;
110+
// //headsetPosNoHeight.y = 0.0f;
111+
// glm::fvec3 aimOrigin = s_wsCameraPosition + (baseYaw * headsetPosNoHeight);
112+
// glm::fquat aimRotation = baseYaw * headsetRot;
113+
// glm::fvec3 aimDirection = glm::normalize(aimRotation * glm::fvec3(0.0f, 0.0f, -1.0f));
114+
115+
// transform.setPos(aimOrigin);
116+
// transform.setRotLE(aimRotation);
117+
// //writeMemory(hCPU->gpr[4], &transform);
118+
119+
// s_lastScreenAimOrigin = aimOrigin;
120+
// s_lastScreenAimAdjustedTarget = aimOrigin + (aimDirection * s_lastScreenAimDistance);
121+
// s_lastScreenAimValid = true;
122+
123+
// Log::print<INFO>("[Arrow Stuff] New pos = {}, rot = {}, aimDir = {}", aimOrigin, aimRotation, aimDirection);
124+
// }
125+
// }
126+
//}
127+
}
128+
129+
void CemuHooks::hook_SetRigidBodyPosition(PPCInterpreter_t* hCPU) {
130+
hCPU->instructionPointer = 0x03486D84;
131+
hCPU->gpr[0] = hCPU->sprNew.LR;
132+
133+
//uint32_t lr = hCPU->sprNew.LR;
134+
//uint32_t rigidBodyAddr = hCPU->gpr[3];
135+
//BEVec3 position;
136+
//readMemory(hCPU->gpr[4], &position);
137+
////Log::print<INFO>("[{:08X}] Set rigid body position of {:08X}: pos = {}", lr, rigidBodyAddr, position);
138+
139+
//DebugDraw::instance().Dot(position.getLE(), 5.0f, IM_COL32(255, 0, 0, 255));
140+
}
141+
142+
void CemuHooks::hook_SetRigidBodyPositionAndRotation(PPCInterpreter_t* hCPU) {
143+
hCPU->instructionPointer = 0x03489A84;
144+
hCPU->gpr[11] = hCPU->gpr[1];
145+
146+
//uint32_t lr = hCPU->sprNew.LR;
147+
//uint32_t rigidBodyAddr = hCPU->gpr[3];
148+
//BEMatrix34 transform;
149+
//readMemory(hCPU->gpr[4], &transform);
150+
151+
//DebugDraw::instance().Dot(transform.getPos().getLE(), 5.0f, IM_COL32(255, 255, 0, 255));
152+
//Log::print<INFO>("[{:08X}] Set rigid body position and rotation of {:08X}: pos = {}, rotation = {}", lr, rigidBodyAddr, transform.getPos().getLE(), transform.getRotLE());
153+
}
154+
155+
void CemuHooks::hook_SetRigidBodyRotation(PPCInterpreter_t* hCPU) {
156+
hCPU->instructionPointer = 0x0348AB24;
157+
hCPU->gpr[0] = hCPU->sprNew.LR;
158+
159+
//uint32_t lr = hCPU->sprNew.LR;
160+
//uint32_t rigidBodyAddr = hCPU->gpr[3];
161+
//BEMatrix34 transform;
162+
//readMemory(hCPU->gpr[4], &transform);
163+
164+
//Log::print<INFO>("[{:08X}] Set rigid body rotation of {:08X}: rotation = {}", lr, rigidBodyAddr, transform.getRotLE());
165+
}

src/utils/update_checker.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#pragma comment(lib, "winhttp.lib")
1212

1313
namespace UpdateChecker {
14-
const std::string CURRENT_VERSION = "0.9.12";
14+
const std::string CURRENT_VERSION = "0.9.13";
1515

1616
static std::string TrimPrefixV(std::string v) {
1717
if (!v.empty() && (v[0] == 'v' || v[0] == 'V')) {

0 commit comments

Comments
 (0)