forked from ReClassNET/ReClass.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCheatEngineFile.cs
More file actions
122 lines (108 loc) · 3.67 KB
/
Copy pathCheatEngineFile.cs
File metadata and controls
122 lines (108 loc) · 3.67 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Text;
using System.Xml.Linq;
using ReClassNET.Logger;
using ReClassNET.MemoryScanner;
namespace ReClassNET.DataExchange.Scanner
{
public class CheatEngineFile : IScannerImport
{
public const string FormatName = "Cheat Engine Tables";
public const string FileExtension = ".ct";
private const string Version26 = "26";
public const string XmlVersionElement = "CheatEngineTableVersion";
public const string XmlEntriesElement = "CheatEntries";
public const string XmlEntryElement = "CheatEntry";
public const string XmlDescriptionElement = "Description";
public const string XmlValueTypeElement = "VariableType";
public const string XmlAddressElement = "Address";
public const string XmlUnicodeElement = "Unicode";
public const string XmlLengthElement = "Length";
public IEnumerable<MemoryRecord> Load(string filePath, ILogger logger)
{
using (var stream = File.OpenRead(filePath))
{
var document = XDocument.Load(stream);
if (document.Root != null)
{
var version = document.Root.Attribute(XmlVersionElement)?.Value;
if (string.Compare(version, Version26, StringComparison.Ordinal) >= 0)
{
var entries = document.Root.Element(XmlEntriesElement);
if (entries != null)
{
foreach (var entry in entries.Elements(XmlEntryElement))
{
var description = entry.Element(XmlDescriptionElement)?.Value.Trim() ?? string.Empty;
if (description == "\"No description\"")
{
description = string.Empty;
}
var variableTypeStr = entry.Element(XmlValueTypeElement)?.Value.Trim() ?? string.Empty;
var valueType = Parse(variableTypeStr, logger);
var record = new MemoryRecord
{
Description = description,
ValueType = valueType
};
var addressStr = entry.Element(XmlAddressElement)?.Value.Trim() ?? string.Empty;
var addressParts = addressStr.Split('+');
if (addressParts.Length == 2)
{
long.TryParse(addressParts[1], NumberStyles.HexNumber, null, out var value);
record.AddressOrOffset = (IntPtr)value;
record.ModuleName = addressParts[0].Trim();
}
else
{
long.TryParse(addressStr, NumberStyles.HexNumber, null, out var value);
record.AddressOrOffset = (IntPtr)value;
}
if (valueType == ScanValueType.ArrayOfBytes || valueType == ScanValueType.String)
{
var lengthStr = entry.Element(XmlLengthElement)?.Value ?? string.Empty;
int.TryParse(lengthStr, NumberStyles.Integer, null, out var valueLength);
record.ValueLength = Math.Max(1, valueLength);
if (valueType == ScanValueType.String)
{
var isUnicode = (entry.Element(XmlUnicodeElement)?.Value ?? string.Empty) == "1";
record.Encoding = isUnicode ? Encoding.Unicode : Encoding.UTF8;
}
}
yield return record;
}
}
}
}
}
}
private static ScanValueType Parse(string value, ILogger logger)
{
switch (value)
{
case "Byte":
return ScanValueType.Byte;
case "2 Bytes":
return ScanValueType.Short;
case "4 Bytes":
return ScanValueType.Integer;
case "8 Bytes":
return ScanValueType.Long;
case "Float":
return ScanValueType.Float;
case "Double":
return ScanValueType.Double;
case "String":
return ScanValueType.String;
case "Array of byte":
return ScanValueType.ArrayOfBytes;
default:
logger?.Log(LogLevel.Warning, $"Unknown value type: {value}");
return ScanValueType.Integer;
}
}
}
}