Skip to content

macOS Unity 6 fixes: restore runtime hooks and native packaging - #5

Open
Zheng-Yu7463 wants to merge 3 commits into
SFGrenade:hk-beta-branch-unity-6-updatefrom
Zheng-Yu7463:codex/macos-unity6
Open

Zheng-Yu7463 wants to merge 3 commits into
SFGrenade:hk-beta-branch-unity-6-updatefrom
Zheng-Yu7463:codex/macos-unity6

Conversation

@Zheng-Yu7463

@Zheng-Yu7463 Zheng-Yu7463 commented Oct 13, 2026 •

Copy link
Copy Markdown

Follow-up to hk-modding#164, based on @SFGrenade's hk-beta-branch-unity-6-update at 468f579. This adapts the Unity 6 branch so EnemyHPBar and Benchwarp run on macOS with Hollow Knight 1.5.12620 (Unity 6000.0.61f1), in both native arm64 and Rosetta game processes.

Fixes

  • Inline prevention was inverted (MonoMod.Patcher/MonoModder.cs): AggressiveInlining was applied instead of cleared, so patched methods stayed inlined and runtime hooks never observed calls. Both game assemblies now build with PreventInline as intended.
  • Legacy hook forwarding across the localization move to TeamCherry.Localization.Language: a [Modding.ForwardedHooks] marker lets HookGenerator retarget On/IL endpoints to the real methods while keeping legacy signatures, including the old LanguageCode enum in parameters and returns. Invalid forwarded facades are rejected at generation time.
  • Menu transition NullReferenceException: the preloader now calls PrepareForMenuTransition() to set the private waitForManualLevelStart before LoadSceneAsync("Quit_To_Menu"), fixing a GameManager.SetupHeroRefs crash. The field has to stay private: making it public changes Unity serialization layout and crashes at runtime.
  • macOS build and packaging: Assembly-CSharp no longer defaults to a game path or copies in place, stages only OutputFinal, packages both native dylibs per RID, always regenerates HookGen output, fixes Pre/PostPatcher build order, and merges the x86-64 and arm64 natives into universal libraries as part of the build itself. The GitHub Actions macOS job installs lipo before building instead of merging afterwards, so local builds and CI produce the same universal libraries. Previously a local Apple Silicon build silently shipped x86-64-only natives, which made UnitySceneRepacker fail in a native arm64 process and Benchwarp teleports time out.

Validation

  • Release and Debug builds: 0 errors. The merged dylibs verify as universal, and their x86-64 slices are byte-identical to the previous x64-only files.
  • New Tests/HookGen regression tests (no game files needed): PASS.
  • Runtime smoke probe on an isolated game copy, native arm64: 37/37. Satchel 0.9.4-b6ec98, EnemyHPBar 3.1.5 and Benchwarp 3.2.6.1 load without initialization errors; resource decoding, menu construction and bench preload succeed; native detour install/original/dispose works; legacy language hooks fire exactly once per call with enum values preserved and unsubscribe clean.
  • Gameplay probe on an isolated game copy, native arm64: 14/14. A real Tutorial_01 Crawler creates an EnemyHPBar and its HP is tracked from 8 to 7; Benchwarp teleports to Town's RestBench marker with the hero active and gameplay resumed.
  • The same gameplay probe under Rosetta (x86-64): 14/14.
  • Real game launched from Steam (native arm64): UnitySceneRepacker loads (Repacked 1 preload scenes from 1146 to 45 objects) and the modded title screen lists all three mods.

Limitations

  • Only Satchel, EnemyHPBar and Benchwarp were validated; save persistence was not exercised. Mods that assume an x86-64 process may still fail on arm64.
  • Windows and Linux code paths changed but were not run locally; CI is the check for those.

The changes can be split into smaller PRs if that is preferred for review.

Copilot AI balanced review requested due to automatic review settings October 13, 2026 12:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

The macOS build copied only the osx-x64 native libraries from the
unityscenerepacker package, while CI merged them with the osx-arm64 ones into
universal binaries afterwards. Local builds therefore shipped x86-64-only
libraries: the game launches natively on Apple Silicon, but
UnitySceneRepacker fails to load in an arm64 process and Benchwarp teleports
time out.

Move the merge into the Assembly-CSharp build itself and let CI install its
lipo binary before the build, so every macOS build produces the same
universal libraries. The x86-64 slice is unchanged for Rosetta launches.

Verified on an M4 with Hollow Knight 1.5.12620: the arm64 game process loads
UnitySceneRepacker and completes a Benchwarp teleport to Town, and the
x86-64 slices of the rebuilt libraries match the previously installed ones
byte for byte.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants