#pragma once #include #include namespace dnf90_companion_p0 { // EXE-specific native ABI. Projection policy, queue, AIC ownership and AI // remain shared. These bindings are selected once, before installing hooks. struct CompanionNativeBindings { size_t kUserInfoKeyOffset = 0xC; size_t kUserInfoLevelOffset = 0x2C; uintptr_t kAIControlledVmVtableRva = 0x0; bool newNative = false; uintptr_t kExpectedReceiveRva = 0x02BBB690; uintptr_t kPayloadEncodeReturnRva = 0x02BB76E0; uintptr_t kWriterPointerRva = 0x04DB275C; uintptr_t kDispatcherPointerRva = 0x04EC12B8; size_t kPacketBufferOffset = 0x20; size_t kWriterCursorOffset = 0x100020; uintptr_t kNativeSummonApcRva = 0x01F134A0; uintptr_t kNativeReadyRva = 0x01FB0BF0; uintptr_t kSceneContextGetterRva = 0x018F2A70; uintptr_t kSceneModeRva = 0x01E64FD0; uintptr_t kNativeRefStringAllocRva = 0x03714DA7; uintptr_t kNativeRefStringFreeRva = 0x037146A3; uintptr_t kNativeRefStringIncIatRva = 0x03DA2348; uintptr_t kNativeRefStringDecIatRva = 0x03DA2344; uintptr_t kNativeVectorFreeRva = 0x0370DEB4; uintptr_t kNativeEquipmentVectorAllocateRva = 0x01CF1340; uintptr_t kNativeSkillVectorAllocateRva = 0x020B2420; size_t kActorDisplayNameOffset = 0x400; size_t kAicEquipmentVectorObjectOffset = 0x49C; size_t kAicQuickSkillVectorObjectOffset = 0x4C4; size_t kAicSkillVectorObjectOffset = 0x4D8; size_t kAicEquipmentVectorOffset = 0x4A0; size_t kAicQuickSkillVectorOffset = 0x4C8; size_t kAicSkillVectorOffset = 0x4DC; size_t kActorAicOffset = 0x6C28; size_t kAicRuntimeKeyProgramVectorOffset = 0xFE0; size_t kRuntimeKeyProgramBytecodeBeginOffset = 0x08; size_t kRuntimeKeyProgramBytecodeEndOffset = 0x0C; size_t kRuntimeKeyProgramBytecodeCapacityOffset = 0x10; size_t kRuntimeKeySkillCodeOffset = 0x100; size_t kRuntimeDirectKeyBytecodeSize = 0x180; uintptr_t kExpectedSerializerRva = 0x02136B60; uintptr_t kControlledActorPointerRva = 0x04EB5BB0; size_t kSerializerVtableOffset = 0x4F0; size_t kActorOwnerContextOffset = 0xBC; size_t kOwnerRuntimeOffset = 0x110; uintptr_t kProjectionReaderStateRva = 0x04EF8500; uintptr_t kProjectionReaderErrorCopyRva = 0x04EF8528; uintptr_t kProjectionReaderSetCursorRva = 0x030E2280; uintptr_t kProjectionReaderSetLengthRva = 0x030E2290; uintptr_t kProjectionReaderSetPacketRva = 0x030E3430; uintptr_t kControlledActorGetterRva = 0; uintptr_t kAIParameterRva = 0x0222A2A0; uintptr_t kAICooldownRva = 0x0222B040; uintptr_t kAIKeyReadyRva = 0x0222B330; uintptr_t kActorClockRva = 0x0222EB60; uintptr_t kClockReadRva = 0x03108170; size_t kActorVmOffset = 0x6F54; size_t kActorKeyVtableOffset = 0x50; size_t kActorAbilityVtableOffset = 0x648; size_t kActorUserInfoVtableOffset = 0xCF4; size_t kAicUserInfoOffset = 0x100C; size_t kActorSpawnLevelOffset = 0x6F1C; size_t kActorExpVtableOffset = 0xA9C; size_t kActorLearnVtableOffset = 0xB60; size_t kActorStatsVtableOffset = 0xAC4; size_t kActorRecalculateVtableOffset = 0xACC; }; inline CompanionNativeBindings NewNativeCompanionBindings() { CompanionNativeBindings b; b.newNative = true; b.kExpectedReceiveRva = 0x2E9BDC0; b.kPayloadEncodeReturnRva = 0x2E97D90; b.kNativeSummonApcRva = 0x21D7580; b.kNativeReadyRva = 0x2276330; b.kSceneContextGetterRva = 0x1BA2790; b.kSceneModeRva = 0x2126B50; b.kNativeRefStringAllocRva = 0x3A77C68; b.kNativeRefStringFreeRva = 0x3A777CB; b.kNativeRefStringIncIatRva = 0x6A85BA8; b.kNativeRefStringDecIatRva = 0x6A85A3C; b.kNativeVectorFreeRva = 0x3A70888; b.kNativeEquipmentVectorAllocateRva = 0x1094240; b.kNativeSkillVectorAllocateRva = 0x10E8E10; b.kActorDisplayNameOffset = 0x404; b.kAicEquipmentVectorObjectOffset = 0x4B4; b.kAicQuickSkillVectorObjectOffset = 0x4DC; b.kAicSkillVectorObjectOffset = 0x4F0; b.kAicEquipmentVectorOffset = 0x4B8; b.kAicQuickSkillVectorOffset = 0x4E0; b.kAicSkillVectorOffset = 0x4F4; b.kActorAicOffset = 0x6CA8; b.kAicRuntimeKeyProgramVectorOffset = 0xFF8; b.kExpectedSerializerRva = 0x2402950; b.kControlledActorGetterRva = 0x25610E0; b.kSerializerVtableOffset = 0x510; b.kActorOwnerContextOffset = 0xC8; b.kProjectionReaderStateRva = 0x53F9AD0; b.kProjectionReaderErrorCopyRva = 0x53F9AF8; b.kProjectionReaderSetCursorRva = 0x33E6970; b.kProjectionReaderSetLengthRva = 0x33E6980; b.kProjectionReaderSetPacketRva = 0x33E7DA0; b.kAIParameterRva = 0x24EDD90; b.kAICooldownRva = 0x24FA120; b.kAIKeyReadyRva = 0x24FA520; b.kActorClockRva = 0x351BA30; b.kClockReadRva = 0x3416310; b.kActorVmOffset = 0x6FE0; b.kActorKeyVtableOffset = 0x58; b.kAicUserInfoOffset = 0x1024; b.kWriterPointerRva = 0x52A3790; b.kDispatcherPointerRva = 0x53C2DDC; b.kActorAbilityVtableOffset = 0x670; b.kActorUserInfoVtableOffset = 0xD20; b.kActorSpawnLevelOffset = 0x6FA8; b.kActorExpVtableOffset = 0xAC8; b.kActorLearnVtableOffset = 0xB8C; b.kActorStatsVtableOffset = 0xAF0; b.kActorRecalculateVtableOffset = 0xAF8; b.kUserInfoKeyOffset = 0x20; b.kUserInfoLevelOffset = 0x44; b.kRuntimeKeySkillCodeOffset = 0x128; b.kRuntimeDirectKeyBytecodeSize = 0x1BC; b.kAIControlledVmVtableRva = 0x42CFA14; return b; } // Locked to DB4ABD49...D2. The controller validates the complete EXE hash; // the DLL also checks PE identity and every entry below before installation. struct CompanionNativeAnchor { uintptr_t rva; unsigned char bytes[16]; }; constexpr CompanionNativeAnchor kNewNativeCompanionAnchors[] = { {0x02E9BDC0, {0x55, 0x8B, 0xEC, 0x6A, 0xFF, 0x68, 0x12, 0x85, 0x25, 0x04, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00}}, // kExpectedReceiveRva {0x021D7580, {0xE9, 0x21, 0x52, 0x06, 0x00, 0xE4, 0xCC, 0x9A, 0xA9, 0x09, 0x2E, 0x91, 0x44, 0xCC, 0x03, 0xB9}}, // kNativeSummonApcRva {0x02276330, {0x56, 0x8B, 0xF1, 0xE8, 0xA8, 0x8E, 0x3A, 0x00, 0x85, 0xC0, 0x74, 0x14, 0xE8, 0x9F, 0x8E, 0x3A}}, // kNativeReadyRva {0x01BA2790, {0xE9, 0x7B, 0xC0, 0x57, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC}}, // kSceneContextGetterRva {0x02126B50, {0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x08, 0x56, 0x8B, 0xF1, 0x8B, 0x0D, 0x88, 0x30, 0x6A, 0x05, 0x85}}, // kSceneModeRva {0x03A77C68, {0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x53, 0x8B, 0x5D, 0x08, 0x83, 0xFB, 0xE0, 0x77, 0x6F, 0x56, 0x57}}, // kNativeRefStringAllocRva {0x03A777CB, {0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x83, 0x7D, 0x08, 0x00, 0x74, 0x2D, 0xFF, 0x75, 0x08, 0x6A, 0x00}}, // kNativeRefStringFreeRva {0x03A70888, {0xFF, 0x25, 0xC0, 0x88, 0x58, 0x04, 0xFF, 0x25, 0xBC, 0x88, 0x58, 0x04, 0x8B, 0xFF, 0x56, 0x8B}}, // kNativeVectorFreeRva {0x01094240, {0x55, 0x8B, 0xEC, 0x56, 0x33, 0xC0, 0x57, 0x8B, 0x7D, 0x08, 0x8B, 0xF1, 0x89, 0x46, 0x04, 0x89}}, // kNativeEquipmentVectorAllocateRva {0x010E8E10, {0x55, 0x8B, 0xEC, 0x56, 0x33, 0xC0, 0x57, 0x8B, 0x7D, 0x08, 0x8B, 0xF1, 0x89, 0x46, 0x04, 0x89}}, // kNativeSkillVectorAllocateRva {0x02402950, {0x55, 0x8B, 0xEC, 0x57, 0x8B, 0xF9, 0x8B, 0x87, 0xC8, 0x00, 0x00, 0x00, 0x85, 0xC0, 0x0F, 0x84}}, // kExpectedSerializerRva {0x025610E0, {0xA1, 0xB4, 0x6F, 0x7B, 0x05, 0x85, 0xC0, 0x75, 0x05, 0xA1, 0xB0, 0x6F, 0x7B, 0x05, 0xC3, 0xCC}}, // kControlledActorGetterRva {0x033E6970, {0xE9, 0x72, 0x59, 0x66, 0x03, 0x8D, 0x64, 0x24, 0x04, 0x57, 0xE9, 0xD8, 0x98, 0x62, 0x03, 0x75}}, // kProjectionReaderSetCursorRva {0x033E6980, {0x55, 0x8B, 0xEC, 0x8B, 0x45, 0x08, 0xA3, 0xD4, 0x9A, 0x7F, 0x05, 0x5D, 0xC3, 0xCC, 0xCC, 0xCC}}, // kProjectionReaderSetLengthRva {0x033E7DA0, {0x55, 0x8B, 0xEC, 0x8B, 0x45, 0x08, 0x8B, 0x4D, 0x0C, 0xA3, 0xD8, 0x9A, 0x7F, 0x05, 0xA1, 0xF8}}, // kProjectionReaderSetPacketRva {0x024EDD90, {0x55, 0x8B, 0xEC, 0x6A, 0xFF, 0x68, 0x58, 0x9D, 0x0D, 0x04, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00}}, // kAIParameterRva {0x024FA120, {0x56, 0x8B, 0xF1, 0x80, 0x7E, 0x6D, 0x00, 0x75, 0x27, 0x83, 0x7E, 0x64, 0x00, 0x74, 0x21, 0x8B}}, // kAICooldownRva {0x024FA520, {0x55, 0x8B, 0xEC, 0x53, 0x56, 0x8B, 0xF1, 0x83, 0x7E, 0x4C, 0x00, 0x57, 0x0F, 0x84, 0xEB, 0x00}}, // kAIKeyReadyRva {0x0351BA30, {0x8D, 0x41, 0x68, 0xC3, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC}}, // kActorClockRva {0x03416310, {0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x10, 0x56, 0x8B, 0xF1, 0x8B, 0x46, 0x0C, 0x8D, 0x4D, 0xF8, 0x51}}, // kClockReadRva {0x0211E340, {0x55, 0x8B, 0xEC, 0x53, 0x8B, 0x5D, 0x0C, 0x57, 0xC6, 0x05, 0x48, 0x27, 0x68, 0x05, 0x00, 0x0F}}, // kClass0Dispatch {0x02123C8A, {0x8A, 0x45, 0xA3, 0xC7, 0x45, 0xAC, 0x01, 0x00, 0x00, 0x00, 0x3C, 0x01, 0x0F, 0x85, 0xAB, 0x02}}, // kDecodedProjectionCapture {0x02364160, {0x55, 0x8B, 0xEC, 0x6A, 0xFF, 0x68, 0x68, 0xB3, 0xF7, 0x03, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00}}, // kAicCopyHook {0x0248A260, {0x55, 0x8B, 0xEC, 0x6A, 0xFF, 0x68, 0x0D, 0x30, 0x1B, 0x04, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00}}, // kRegistrationHook {0x024F98B0, {0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x14, 0x53, 0x56, 0x8B, 0xF1, 0x8B, 0x46, 0x1C, 0x57, 0x83, 0xF8}}, // kAIConditionHook {0x034FB0E0, {0xE9, 0x00, 0x11, 0x52, 0x03, 0x8D, 0x64, 0x24, 0x04, 0x53, 0x50, 0x56, 0x9C, 0x55, 0x57, 0xE9}}, // kPeerDeliveryHook {0x02E83610, {0x55, 0x8B, 0xEC, 0x83, 0xEC, 0x08, 0x53, 0x56, 0x8B, 0x75, 0x10, 0x57, 0xBB, 0xB5, 0x3E, 0x45}}, // kPayloadEncoderHook {0x0256D730, {0x55, 0x8B, 0xEC, 0xA1, 0x58, 0x37, 0x6A, 0x05, 0x83, 0xEC, 0x1C, 0x53, 0x66, 0x8B, 0x5D, 0x08}}, // kActorLookupHook {0x033DF130, {0x55, 0x8B, 0xEC, 0xA1, 0x78, 0x8A, 0x7F, 0x05, 0x40, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x0F, 0xB6}}, // levelWriter0x33df130 {0x033DF1B0, {0x55, 0x8B, 0xEC, 0xA1, 0x78, 0x8A, 0x7F, 0x05, 0x40, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x0F, 0xB6}}, // levelWriter0x33df1b0 {0x033DF230, {0x55, 0x8B, 0xEC, 0xA1, 0x78, 0x8A, 0x7F, 0x05, 0x40, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x0F, 0xB6}}, // levelWriter0x33df230 {0x033DF2B0, {0x55, 0x8B, 0xEC, 0xA1, 0x78, 0x8A, 0x7F, 0x05, 0x40, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x0F, 0xB6}}, // levelWriter0x33df2b0 {0x033DF010, {0x55, 0x8B, 0xEC, 0xA1, 0x78, 0x8A, 0x7F, 0x05, 0x40, 0x8B, 0xD0, 0xC1, 0xEA, 0x08, 0x0F, 0xB6}}, // levelWriter0x33df010 }; } // namespace dnf90_companion_p0