static unsafe NativeTranslator() { if (!File.Exists(NativesXmlFilePath)) { throw new FileNotFoundException("Missing 'NativeWatcher.Natives.xml' file."); } Xml.Natives n; XmlSerializer serializer = new XmlSerializer(typeof(Xml.Natives)); using (StreamReader reader = new StreamReader(NativesXmlFilePath)) { n = (Xml.Natives)serializer.Deserialize(reader); } // build originalToName dictionary originalToName = new Dictionary <ulong, string>(n.OriginalToName.Length); foreach (Xml.NativesOriginalToNameTableEntry e in n.OriginalToName) { originalToName.Add(UInt64.Parse(e.Original, System.Globalization.NumberStyles.HexNumber), e.Name); } // build currentToOriginal dictionary int gameVersion = Rage.Game.BuildNumber; Xml.NativesToOriginalTable table = n.ToOriginal.FirstOrDefault(t => t.Version == gameVersion); if (table == null) { throw new InvalidOperationException($"Missing native hashes translation for version v{gameVersion}."); } currentToOriginal = new Dictionary <ulong, ulong>(table.Entries.Length); foreach (Xml.NativesToOriginalTableEntry e in table.Entries) { currentToOriginal.Add(UInt64.Parse(e.Current, System.Globalization.NumberStyles.HexNumber), UInt64.Parse(e.Original, System.Globalization.NumberStyles.HexNumber)); } // build addressToCurrent dictionary addressToCurrent = new Dictionary <ulong, ulong>(); NativeRegistration **nativesTable = NativeRegistration.GetRegistrationTable(); for (int i = 0; i < 256; i++) { NativeRegistration *t = nativesTable[i]; for (; t != null; t = t->Next) { for (uint k = 0; k < t->EntriesCount; k++) { if (!addressToCurrent.ContainsKey(t->HandlersPointers[k])) { addressToCurrent.Add(t->HandlersPointers[k], t->Hashes[k]); } } } } }
public static NativeRegistration **GetRegistrationTable() { if (registrationTable == null) { IntPtr address = Game.FindPattern("48 8D 0D ?? ?? ?? ?? 4E 8B 1C C7 41 0F B6 C3 48 8B 0C C1"); address = address + *(int *)(address + 3) + 7; registrationTable = (NativeRegistration **)address; } return(registrationTable); }