internal.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172
  1. #pragma once
  2. #include "../../hooking/detour.h"
  3. #include "../../patterns/image_scan.h"
  4. namespace sunrise::client::hooks::bootflow {
  5. using patterns::resolve_relative;
  6. using patterns::scan_main_image_unique;
  7. using patterns::signature;
  8. using patterns::signature_length;
  9. /**
  10. * One boot-step fix resolves its target, then the group attaches every resolved fix together.
  11. * Splitting the two halves is what lets the group hold one detour transaction instead of one per
  12. * fix. A transaction enlists every thread on the system to find this process's own, which costs
  13. * far more than the attach it guards, so the count of transactions is what the boot pays for.
  14. *
  15. * A publish call is made only for a fix that staged, and takes a detached handle when the group's
  16. * attach did not happen.
  17. */
  18. enum class StageResult : unsigned char {
  19. /** The target is missing. The fix reported that itself and staged nothing. */
  20. unavailable,
  21. /** An earlier install already attached this fix, so there is nothing to stage. */
  22. attached,
  23. /** The spec is filled and the fix wants attaching. */
  24. staged,
  25. };
  26. /**
  27. * Stages the character-select hold, which stops the sign-in step auto-selecting.
  28. * @param spec Receives the target and replacement.
  29. * @return staged when the target was found, unavailable on a miss.
  30. */
  31. [[nodiscard]] StageResult stage_character_select_hold(hooking::detour::Spec& spec) noexcept;
  32. /** Takes the character-select hold's attached handle, or a detached one. */
  33. void publish_character_select_hold(const hooking::detour::Handle& handle) noexcept;
  34. /** Detaches the character-select hold. */
  35. void uninstall_character_select_hold() noexcept;
  36. /**
  37. * Stages the profile-setup skip, which skips the startup setup screens.
  38. * @param spec Receives the target and replacement.
  39. * @return staged when the target was found, unavailable on a miss.
  40. */
  41. [[nodiscard]] StageResult stage_profile_setup_skip(hooking::detour::Spec& spec) noexcept;
  42. /** Takes the profile-setup skip's attached handle, or a detached one. */
  43. void publish_profile_setup_skip(const hooking::detour::Handle& handle) noexcept;
  44. /** Detaches the profile-setup skip. */
  45. void uninstall_profile_setup_skip() noexcept;
  46. /**
  47. * Stages the orbit slice-set picker, so the sign-in step's map load finds its target.
  48. * @param spec Receives the target and replacement.
  49. * @return staged when the picker was found, unavailable on a miss.
  50. */
  51. [[nodiscard]] StageResult stage_orbit_slice_set(hooking::detour::Spec& spec) noexcept;
  52. /** Takes the orbit slice-set picker's attached handle, or a detached one. */
  53. void publish_orbit_slice_set(const hooking::detour::Handle& handle) noexcept;
  54. /** Detaches the orbit slice-set picker. */
  55. void uninstall_orbit_slice_set() noexcept;
  56. /**
  57. * Stages the solo composition fix, which clears the count the matchmaking check rejects.
  58. * @param spec Receives the target and replacement.
  59. * @return staged when the target was found, unavailable on a miss.
  60. */
  61. [[nodiscard]] StageResult stage_composition_check(hooking::detour::Spec& spec) noexcept;
  62. /** Takes the solo composition fix's attached handle, or a detached one. */
  63. void publish_composition_check(const hooking::detour::Handle& handle) noexcept;
  64. /** Detaches the solo composition fix. */
  65. void uninstall_composition_check() noexcept;
  66. /**
  67. * Stages the orbit handoff release, which stops the destination step parking.
  68. * @param spec Receives the target and replacement.
  69. * @return staged when the target was found, unavailable on a miss.
  70. */
  71. [[nodiscard]] StageResult stage_orbit_handoff(hooking::detour::Spec& spec) noexcept;
  72. /** Takes the orbit handoff release's attached handle, or a detached one. */
  73. void publish_orbit_handoff(const hooking::detour::Handle& handle) noexcept;
  74. /** Detaches the orbit handoff release. */
  75. void uninstall_orbit_handoff() noexcept;
  76. /**
  77. * Stages the owner activity slot force. It pins the participation record to the replicated
  78. * snapshot at `comp + 496` instead of the local one at `comp + 1256`.
  79. * @param spec Receives the target and replacement.
  80. * @return staged when the target was found, unavailable on a miss.
  81. */
  82. [[nodiscard]] StageResult stage_owner_activity_slot(hooking::detour::Spec& spec) noexcept;
  83. /** Takes the owner activity slot force's attached handle, or a detached one. */
  84. void publish_owner_activity_slot(const hooking::detour::Handle& handle) noexcept;
  85. /** Detaches the owner activity slot force. */
  86. void uninstall_owner_activity_slot() noexcept;
  87. /**
  88. * Stages the private-region force, so a public region takes the path a private one takes.
  89. * A public region otherwise holds its slice-set switch until a public activity host connects.
  90. * @param spec Receives the target and replacement.
  91. * @return staged when both targets and the call site were found, unavailable on a miss.
  92. */
  93. [[nodiscard]] StageResult stage_region_private(hooking::detour::Spec& spec) noexcept;
  94. /** Takes the private-region force's attached handle, or a detached one. */
  95. void publish_region_private(const hooking::detour::Handle& handle) noexcept;
  96. /** Detaches the private-region force. */
  97. void uninstall_region_private() noexcept;
  98. /**
  99. * Finds the boot-flow step accessor, the only input to the world phase.
  100. * Nothing is detoured: the accessor is called, so a miss leaves the phase idle.
  101. * @return True when the target was found.
  102. */
  103. [[nodiscard]] bool install_world_step() noexcept;
  104. /** Clears the boot-flow step accessor it found. */
  105. void uninstall_world_step() noexcept;
  106. /**
  107. * Maps the client's own boot-flow step onto the world phase.
  108. * Runs on the spawn gate poll, which is the only tick the phase is read on.
  109. */
  110. void observe_world_step() noexcept;
  111. /**
  112. * Stages the spawn hold, which puts the player spawn after the world-transition fade is armed.
  113. * @param spec Receives the target and replacement.
  114. * @return staged when the target was found, unavailable on a miss.
  115. */
  116. [[nodiscard]] StageResult stage_spawn_hold(hooking::detour::Spec& spec) noexcept;
  117. /** Takes the spawn hold's attached handle, or a detached one. */
  118. void publish_spawn_hold(const hooking::detour::Handle& handle) noexcept;
  119. /** Detaches the spawn hold. */
  120. void uninstall_spawn_hold() noexcept;
  121. /**
  122. * Finds the world-transition fade release and its manager object.
  123. * Nothing is detoured: both are called, so a miss leaves the feature off, not the client changed.
  124. * @return True when both targets were found.
  125. */
  126. [[nodiscard]] bool install_fade_release() noexcept;
  127. /** Clears the fade release it found. */
  128. void uninstall_fade_release() noexcept;
  129. /**
  130. * Releases the world-transition fade channel.
  131. * The spawn gate owns the timing. Does nothing unless `client.fade_release` is set.
  132. */
  133. void release_world_fade() noexcept;
  134. /** Re-arms the one line the release logs, so the next load reports its own. */
  135. void rearm_fade_release() noexcept;
  136. } // namespace sunrise::client::hooks::bootflow