#ifndef MOCKTAIL_COMPAT_BUILD_PROFILE_H_ #define MOCKTAIL_COMPAT_BUILD_PROFILE_H_ #include #include #include #include #include #include namespace mocktail::compat { enum class BuildStatus { kSupported, kExperimental, kLegacyResearched, kUnverified, }; struct FmodOutputDeviceBridgeProfile { std::uintptr_t vtable_rva = 0; std::uintptr_t string_constructor_rva = 0; std::uintptr_t count_method_rva = 0; std::uintptr_t info_method_rva = 0; std::uintptr_t current_method_rva = 0; std::uintptr_t select_method_rva = 0; // Roblox 2.738 inserted device-list methods before the current/select slots. int vtable_layout_version = 1; // Optional exact-build input count/info/current/select methods. std::array input_method_rvas{}; bool has_input_devices() const { return input_method_rvas[0] != 0; } std::array input_vtable_indexes() const { return vtable_layout_version == 2 ? std::array{9, 10, 12, 18} : std::array{8, 9, 10, 16}; } bool valid_vtable_layout() const { return vtable_layout_version == 1 || vtable_layout_version == 2; } std::size_t current_vtable_index() const { return vtable_layout_version == 2 ? 8 : 7; } std::size_t select_vtable_index() const { return vtable_layout_version == 2 ? 19 : 17; } }; struct BuildProfile { std::string version_name; int version_code = 0; std::string elf_build_id; BuildStatus status = BuildStatus::kUnverified; bool default_allowed = false; bool allow_legacy_binary_patches = false; bool allow_host_abi_bridges = false; bool allow_host_constructor_replay = false; // Optional, exact-build native capability. This is an invoked entrypoint, // never a writable binary patch; the adapter validates its code contract // before the first call. std::optional user_game_settings_fullscreen_setter_rva; // Optional exact-build host ABI bridge. It temporarily interposes only the // output-device virtual slots and restores them during controlled teardown; // executable guest code is never modified. std::optional fmod_output_device_bridge; std::string reason; }; struct ProfileLookupResult { std::optional profile; std::string error; explicit operator bool() const noexcept { return error.empty(); } }; ProfileLookupResult FindBuildProfile(const std::string& manifest_path, std::string_view build_id); std::string_view BuildStatusName(BuildStatus status) noexcept; } // namespace mocktail::compat #endif // MOCKTAIL_COMPAT_BUILD_PROFILE_H_