mirror of
https://git.chinosk6.cn/chinosk/gkms-localify-dmm.git
synced 2026-10-06 05:18:06 +07:00
fix: restore gyro and meishi fixes for v3.5.0
This commit is contained in:
1 parent
d372b0d22c
commit
9462265bca
6 files changed
+83
-30
No files matched your search
@@ -38,12 +38,8 @@ namespace GakumasLocal::GyroEmu {
|
||||
dragging = false;
|
||||
}
|
||||
|
||||
// 小键盘:4/6 yaw, 8/2 pitch, 7/9 roll, 5 复位
|
||||
// 小键盘:7/9 翻滚, 5 复位。4/6/8/2 是游戏自己拍摄页的镜头键,不占用
|
||||
const float step = 60.f * dt * Config::gyroSensitivity;
|
||||
if (Down(VK_NUMPAD4)) yaw -= step * sx;
|
||||
if (Down(VK_NUMPAD6)) yaw += step * sx;
|
||||
if (Down(VK_NUMPAD8)) pitch -= step * sy;
|
||||
if (Down(VK_NUMPAD2)) pitch += step * sy;
|
||||
if (Down(VK_NUMPAD7)) roll += step;
|
||||
if (Down(VK_NUMPAD9)) roll -= step;
|
||||
if (Down(VK_NUMPAD5)) Reset();
|
||||
|
||||
@@ -234,52 +234,92 @@ namespace GakumasLocal::HookMain {
|
||||
return Photography3DPresenter_get_IsGyroSupported_Orig(self, mtd);
|
||||
}
|
||||
|
||||
// PC 版把 LiveUtility.IsPanoramaGyroDisabledOnPlatform()(恒 true)内联成常量,CampusGyroController 根本不会被
|
||||
// 创建/初始化(log 证实 IsGyroAvailable 从未被查询),IsGyroReady 永远 false。这里在 LateUpdate 里自己把它建出来。
|
||||
// PC 版把 LiveUtility.IsPanoramaGyroDisabledOnPlatform()(恒 true)内联成常量,CampusGyroController 的 InitializeAsync
|
||||
// 被整段跳过(log 证实 IsGyroAvailable 从未被查询),IsGyroReady 永远 false。Live 与拍摄各持有一个控制器,
|
||||
// 所以在构造函数 hook 里统一把它置成初始化完成态,再在两条链路各留一个“控制器为空就自己建”的兜底。
|
||||
// 字段偏移来自 3.3.0 il2cpp.h(CampusGyroController / VLGyro / LivePanoramaCameraManager)。
|
||||
namespace GyroForceInit {
|
||||
using Quaternion = UnityResolve::UnityType::Quaternion;
|
||||
template <typename T> T& F(void* obj, size_t off) { return *reinterpret_cast<T*>(reinterpret_cast<char*>(obj) + off); }
|
||||
|
||||
void Ensure(void* manager) {
|
||||
static auto ctrlClass = Il2cppUtils::GetClass("campus-submodule.Runtime.dll", "Campus.Common", "CampusGyroController");
|
||||
static auto gyroClass = Il2cppUtils::GetClass("vl-unity.Runtime.dll", "VL", "VLGyro");
|
||||
static auto ctrlCtor = reinterpret_cast<void (*)(void*, void*)>(Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common", "CampusGyroController", ".ctor"));
|
||||
static auto gyroCtor = reinterpret_cast<void (*)(void*, void*)>(Il2cppUtils::GetMethodPointer("vl-unity.Runtime.dll", "VL", "VLGyro", ".ctor"));
|
||||
static auto gyroReset = reinterpret_cast<void (*)(void*, void*)>(Il2cppUtils::GetMethodPointer("vl-unity.Runtime.dll", "VL", "VLGyro", "ResetRotation"));
|
||||
static auto gyroRaw = reinterpret_cast<Quaternion* (*)(Quaternion*, void*, void*)>(Il2cppUtils::GetMethodPointer("vl-unity.Runtime.dll", "VL", "VLGyro", "get_gyroRotationRaw"));
|
||||
static bool reported = false;
|
||||
if (!ctrlClass || !gyroClass || !ctrlCtor || !gyroCtor || !gyroReset || !gyroRaw) {
|
||||
if (!reported) { reported = true; Log::ErrorFmt("[GyroEmu] force-init: missing class/method (%p %p %p %p %p %p)", ctrlClass, gyroClass, ctrlCtor, gyroCtor, gyroReset, gyroRaw); }
|
||||
return;
|
||||
}
|
||||
struct Api {
|
||||
UnityResolve::Class* ctrlClass; UnityResolve::Class* gyroClass;
|
||||
void (*ctrlCtor)(void*, void*); void (*gyroCtor)(void*, void*); void (*gyroReset)(void*, void*);
|
||||
Quaternion* (*gyroRaw)(Quaternion*, void*, void*);
|
||||
};
|
||||
static const Api* GetApi() {
|
||||
static Api api{
|
||||
Il2cppUtils::GetClass("campus-submodule.Runtime.dll", "Campus.Common", "CampusGyroController"),
|
||||
Il2cppUtils::GetClass("vl-unity.Runtime.dll", "VL", "VLGyro"),
|
||||
reinterpret_cast<void (*)(void*, void*)>(Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common", "CampusGyroController", ".ctor")),
|
||||
reinterpret_cast<void (*)(void*, void*)>(Il2cppUtils::GetMethodPointer("vl-unity.Runtime.dll", "VL", "VLGyro", ".ctor")),
|
||||
reinterpret_cast<void (*)(void*, void*)>(Il2cppUtils::GetMethodPointer("vl-unity.Runtime.dll", "VL", "VLGyro", "ResetRotation")),
|
||||
reinterpret_cast<Quaternion* (*)(Quaternion*, void*, void*)>(Il2cppUtils::GetMethodPointer("vl-unity.Runtime.dll", "VL", "VLGyro", "get_gyroRotationRaw")),
|
||||
};
|
||||
static const bool ok = [] {
|
||||
if (api.ctrlClass && api.gyroClass && api.ctrlCtor && api.gyroCtor && api.gyroReset && api.gyroRaw) return true;
|
||||
Log::ErrorFmt("[GyroEmu] force-init: missing class/method (%p %p %p %p %p %p)", api.ctrlClass, api.gyroClass, api.ctrlCtor, api.gyroCtor, api.gyroReset, api.gyroRaw);
|
||||
return false;
|
||||
}();
|
||||
return ok ? &api : nullptr;
|
||||
}
|
||||
|
||||
// 把一个已构造的 CampusGyroController 直接置成“初始化完成”态(等价于它自己 InitializeAsync 成功后的状态)
|
||||
void InitController(void* ctrl) {
|
||||
auto api = GetApi();
|
||||
if (!api || !ctrl || F<bool>(ctrl, 0x18)) return; // _initialized
|
||||
const Quaternion identity(0, 0, 0, 1);
|
||||
auto& ctrl = F<void*>(manager, 0x60); // _gyroController
|
||||
if (!ctrl) { ctrl = ctrlClass->New<void*>(); ctrlCtor(ctrl, nullptr); }
|
||||
if (F<bool>(ctrl, 0x18)) return; // _initialized
|
||||
auto& gyro = F<void*>(ctrl, 0x10); // _gyro
|
||||
if (!gyro) { gyro = gyroClass->New<void*>(); gyroCtor(gyro, nullptr); }
|
||||
if (!gyro) { gyro = api->gyroClass->New<void*>(); api->gyroCtor(gyro, nullptr); }
|
||||
F<int>(gyro, 0x14) = 1; // _updateType = Gyro
|
||||
F<bool>(gyro, 0x29) = true; // gyroSupported
|
||||
F<bool>(gyro, 0x2A) = true; // _defaultGyroEnable
|
||||
for (size_t off : {0x2C, 0x3C, 0x4C, 0x5C}) F<Quaternion>(gyro, off) = identity;
|
||||
F<bool>(gyro, 0x6C) = true; // _initialized
|
||||
F<bool>(gyro, 0x6D) = true; // _firstUpdate
|
||||
gyroReset(gyro, nullptr);
|
||||
Quaternion raw; gyroRaw(&raw, gyro, nullptr);
|
||||
api->gyroReset(gyro, nullptr);
|
||||
Quaternion raw; api->gyroRaw(&raw, gyro, nullptr);
|
||||
F<Quaternion>(ctrl, 0x1C) = Quaternion(-raw.x, -raw.y, -raw.z, raw.w); // _baseRotation = Inverse(raw)
|
||||
F<int>(ctrl, 0x2C) = INT_MIN; // _lastAccessFrame
|
||||
F<Quaternion>(ctrl, 0x30) = identity; // _rotation
|
||||
F<bool>(ctrl, 0x18) = true; // _initialized
|
||||
Log::InfoFmt("[GyroEmu] force-init done: controller %p gyro %p", ctrl, gyro);
|
||||
}
|
||||
|
||||
void* NewController() {
|
||||
auto api = GetApi();
|
||||
if (!api) return nullptr;
|
||||
auto ctrl = api->ctrlClass->New<void*>();
|
||||
api->ctrlCtor(ctrl, nullptr); // 构造函数 hook 会顺手 InitController
|
||||
InitController(ctrl);
|
||||
return ctrl;
|
||||
}
|
||||
}
|
||||
|
||||
// 所有 CampusGyroController 一出生就初始化完成,Live / 拍摄 / 其他持有者都不用再关心 PC 上被跳过的 InitializeAsync
|
||||
DEFINE_HOOK(void, CampusGyroController_ctor, (void* self, void* mtd)) {
|
||||
CampusGyroController_ctor_Orig(self, mtd);
|
||||
if (Config::enableGyroEmu) GyroForceInit::InitController(self);
|
||||
}
|
||||
|
||||
// Live:PC 版可能连控制器都没建,LateUpdate 里兜底
|
||||
DEFINE_HOOK(void, LivePanoramaCameraManager_LateUpdate, (void* self, void* mtd)) {
|
||||
if (Config::enableGyroEmu && self) GyroForceInit::Ensure(self);
|
||||
if (Config::enableGyroEmu && self) {
|
||||
auto& ctrl = GyroForceInit::F<void*>(self, 0x60); // _gyroController
|
||||
if (!ctrl) ctrl = GyroForceInit::NewController();
|
||||
else GyroForceInit::InitController(ctrl);
|
||||
}
|
||||
LivePanoramaCameraManager_LateUpdate_Orig(self, mtd);
|
||||
}
|
||||
|
||||
// 拍摄:PhotographySceneManager 把控制器交给 PhotographyActivityController,这里是它进相机控制器的唯一入口
|
||||
DEFINE_HOOK(void, PhotographyActivityController_Initialize, (void* self, void* volumeProfile, void* gyroController, float arg, void* mtd)) {
|
||||
if (Config::enableGyroEmu) {
|
||||
if (!gyroController) gyroController = GyroForceInit::NewController();
|
||||
else GyroForceInit::InitController(gyroController);
|
||||
}
|
||||
PhotographyActivityController_Initialize_Orig(self, volumeProfile, gyroController, arg, mtd);
|
||||
}
|
||||
// PC 版 MSVC 把 SystemInfo.supportsGyroscope / Gyroscope.* 这些托管包装内联进了调用方,hook 函数本体拦不到。
|
||||
// il2cpp 的 icall 包装里有一个 static 缓存指针(_il2cpp_icall_func),内联后所有副本共用同一个变量,
|
||||
// 直接把这个变量改成我们的函数即可,不碰任何机器码,也不受链接器 ICF 合并影响。
|
||||
@@ -1459,10 +1499,21 @@ namespace GakumasLocal::HookMain {
|
||||
return ret;
|
||||
}*/
|
||||
|
||||
// 名片编辑页的 P 偶像页签用 UserIdolCardSkinList.Exists(skin.Id) 过滤“拥有的皮肤”,随后按底卡去
|
||||
// UserIdolCardList 查 UserIdolCard 取 IllustrationStage。下面 Exists 对所有 i_card-skin-* 返回 true 会把
|
||||
// 没有底卡的皮肤也放进去,查到 null 直接 NRE,整个界面初始化中断(表现为卡死)。该模型构造期间放行真实结果。
|
||||
static bool meishiModelConstructing = false;
|
||||
DEFINE_HOOK(void, MeishiBasePIdolTabPageModel_ctor, (void* self, void* mtd)) {
|
||||
meishiModelConstructing = true;
|
||||
MeishiBasePIdolTabPageModel_ctor_Orig(self, mtd);
|
||||
meishiModelConstructing = false;
|
||||
}
|
||||
|
||||
DEFINE_HOOK(bool, UserIdolCardSkinCollection_Exists, (void* self, Il2cppString* id, void* mtd)) { // Live默认选择
|
||||
auto ret = UserIdolCardSkinCollection_Exists_Orig(self, id, mtd);
|
||||
// Log::DebugFmt("UserIdolCardSkinCollection_Exists: %s, ret: %d", id->ToString().c_str(), ret);
|
||||
if (!(Config::dbgMode && Config::unlockAllLive)) return ret;
|
||||
if (meishiModelConstructing) return ret;
|
||||
|
||||
if (id) {
|
||||
std::string idStr = id->ToString();
|
||||
@@ -2842,6 +2893,8 @@ namespace GakumasLocal::HookMain {
|
||||
if (UserIdolCardSkinCollection_Exists_mtd) {
|
||||
ADD_HOOK(UserIdolCardSkinCollection_Exists, UserIdolCardSkinCollection_Exists_mtd->methodPointer);
|
||||
}
|
||||
ADD_HOOK(MeishiBasePIdolTabPageModel_ctor, Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.OutGame",
|
||||
"MeishiBasePIdolTabPageModel", ".ctor"));
|
||||
|
||||
auto UserCostumeCollection_klass = Il2cppUtils::GetClass("Assembly-CSharp.dll", "Campus.Common.User",
|
||||
"UserCostumeCollection");
|
||||
@@ -3044,6 +3097,10 @@ namespace GakumasLocal::HookMain {
|
||||
GyroIcall::Install();
|
||||
ADD_HOOK(LivePanoramaCameraManager_LateUpdate, Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Live",
|
||||
"LivePanoramaCameraManager", "LateUpdate"));
|
||||
ADD_HOOK(CampusGyroController_ctor, Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Common",
|
||||
"CampusGyroController", ".ctor"));
|
||||
ADD_HOOK(PhotographyActivityController_Initialize, Il2cppUtils::GetMethodPointer("campus-submodule.Runtime.dll", "Campus.Photography",
|
||||
"PhotographyActivityController", "Initialize"));
|
||||
|
||||
ADD_HOOK(WindowHandle_SetWindowLong, Il2cppUtils::GetMethodPointer("Assembly-CSharp.dll", "Campus.Common.StandAloneWindow",
|
||||
"WindowHandle", "SetWindowLong"));
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace I18nData {
|
||||
{ "lazy_init", "Fast Initialization (Lazy loading)" },
|
||||
{ "enable_free_camera", "Enable Free Camera" },
|
||||
{ "enable_gyro_emu", "Enable Gyroscope Emulation (Live/Photo)" },
|
||||
{ "gyro_emu_help", "Hold right mouse button and drag to rotate; Numpad 4/6 8/2 yaw/pitch, 7/9 roll, 5 reset" },
|
||||
{ "gyro_emu_help", "Hold right mouse button and drag to rotate; Numpad 7/9 roll, 5 reset" },
|
||||
{ "gyro_sensitivity", "Gyro Sensitivity" },
|
||||
{ "gyro_invert_x", "Invert X" },
|
||||
{ "gyro_invert_y", "Invert Y" },
|
||||
|
||||
@@ -58,7 +58,7 @@ namespace I18nData {
|
||||
{ "enable_breast_param", "胸のパラメーターを有効化" },
|
||||
{ "enable_free_camera", "フリーカメラを有効化" },
|
||||
{ "enable_gyro_emu", "ジャイロ模擬を有効化(ライブ/撮影)" },
|
||||
{ "gyro_emu_help", "右クリックドラッグで視点回転;テンキー 4/6 8/2 左右上下, 7/9 ロール, 5 リセット" },
|
||||
{ "gyro_emu_help", "右クリックドラッグで視点回転;テンキー 7/9 ロール, 5 リセット" },
|
||||
{ "gyro_sensitivity", "ジャイロ感度" },
|
||||
{ "gyro_invert_x", "左右反転" },
|
||||
{ "gyro_invert_y", "上下反転" },
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace I18nData {
|
||||
{ "lazy_init", "快速初始化(懒加载配置)" },
|
||||
{ "enable_free_camera", "启用自由视角(可热重载; 需使用实体键盘)" },
|
||||
{ "enable_gyro_emu", "启用陀螺仪模拟(Live/拍摄)" },
|
||||
{ "gyro_emu_help", "按住鼠标右键拖动转动视角;小键盘 4/6 8/2 左右上下, 7/9 翻滚, 5 复位" },
|
||||
{ "gyro_emu_help", "按住鼠标右键拖动转动视角;小键盘 7/9 翻滚, 5 复位" },
|
||||
{ "gyro_sensitivity", "陀螺仪灵敏度" },
|
||||
{ "gyro_invert_x", "反转左右" },
|
||||
{ "gyro_invert_y", "反转上下" },
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace I18nData {
|
||||
{ "lazy_init", "快速初始化(懶人設定)" },
|
||||
{ "enable_free_camera", "啟用自由視角(可熱重載; 需使用實體鍵盤)" },
|
||||
{ "enable_gyro_emu", "啟用陀螺儀模擬(Live/拍攝)" },
|
||||
{ "gyro_emu_help", "按住滑鼠右鍵拖動轉動視角;數字鍵盤 4/6 8/2 左右上下, 7/9 翻滾, 5 重設" },
|
||||
{ "gyro_emu_help", "按住滑鼠右鍵拖動轉動視角;數字鍵盤 7/9 翻滾, 5 重設" },
|
||||
{ "gyro_sensitivity", "陀螺儀靈敏度" },
|
||||
{ "gyro_invert_x", "反轉左右" },
|
||||
{ "gyro_invert_y", "反轉上下" },
|
||||
|
||||
Reference in new issue
Block a user