Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 7 additions & 4 deletions src/register.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ MAKE_HOOK(LivenessState_TraverseGCDescriptor, (nullptr), void, Il2CppObject* obj
// val is: pointer to BeatmapDifficulty[] (at least, it SHOULD be)
// specifically, val is a pointer to: 39D0 before obj
// Offset of filter class
auto filterClass = *reinterpret_cast<Il2CppClass**>(reinterpret_cast<uintptr_t>(state) + 0x10);
auto filterClass = *reinterpret_cast<Il2CppClass**>(reinterpret_cast<uintptr_t>(state) + 0x08);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we swap this to the actual state structure from the il2cpp headers? I think that'll make it work more cleanly and across different versions of unity too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The struct is in a .cpp, we dont have access

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've discussed this before with you. Just copy the struct and use it :I

@sc2ad sc2ad Aug 10, 2026 •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we shouldn't copy it here since that'll effectively be the same issue as the hard coded offset, but it'll be better than the hard coded offset, so we can do that if there's too much garbage in the cpp to include it directly.

I think we can try getting pieces of this structure out, but that's probably out of scope. I'm mostly worried about support for different unity versions. Can we guard this with the unity_* defines to one or the other?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the struct would make the easier far easier to resolve in future versions instead of offset math that we can easily get wrong.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we shouldn't copy it here since that'll effectively be the same issue as the hard coded offset, but it'll be better than the hard coded offset, so we can do that if there's too much garbage in the cpp to include it directly.

I think we can try getting pieces of this structure out, but that's probably out of scope. I'm mostly worried about support for different unity versions. Can we guard this with the unity_* defines to one or the other?

We can but so far i observed same offset on unity2022 & 6

if (!val->klass || (GET_CLASS(val)->has_references == 0 && GET_CLASS(val)->klass != GET_CLASS(val) && GET_CLASS(val)->name == nullptr) ||
// If our filter class is not null, and
// our filter class' type hierarchy depth is <= ours and
Expand Down Expand Up @@ -439,9 +439,12 @@ MAKE_HOOK(LivenessState_TraverseGCDescriptor, (nullptr), void, Il2CppObject* obj
custom_types::logAll(GET_CLASS(obj));
}
custom_types::logger.critical("KLASS PTR: {}", fmt::ptr(val->klass));
custom_types::logger.critical("Attempting HasParentUnsafe({}, {})...", fmt::ptr(GET_CLASS(val)), fmt::ptr(filterClass));
auto ret = HasParentUnsafe(GET_CLASS(val), filterClass);
custom_types::logger.critical("HasParentUnsafe return: {}", ret);
if (filterClass) {
custom_types::logger.critical("Attempting HasParentUnsafe({}, {})...", fmt::ptr(GET_CLASS(val)), fmt::ptr(filterClass));
auto ret = HasParentUnsafe(GET_CLASS(val), filterClass);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Iirc, there were two reasons for this.

  1. We want to still print even when filter class was null
  2. Calling with a null filter class would behave the same as what hasparentunsafe did, that is, if this function was already called with a null filter class, then it would crash in the same place if there were no checks inside the logic of hasparentunsafe

custom_types::logger.critical("HasParentUnsafe return: {}", ret);
}

if (GET_CLASS(val)) {
custom_types::logAll(GET_CLASS(val));
}
Expand Down
Loading