Added parser for CT files
Early support for Cheat Engine memory tweaks
This commit is contained in:
parent
6b6f6265f5
commit
c6968ebb8a
|
@ -64,6 +64,8 @@
|
|||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="DebuggerExtras\CheatTable.cs" />
|
||||
<Compile Include="DebuggerExtras\CheatTableReader.cs" />
|
||||
<Compile Include="DebuggerSymbols\Kernel\KernelSymbolProvider.cs" />
|
||||
<Compile Include="Debugger\Debugger.cs" />
|
||||
<Compile Include="Debugger\DebuggerEventInterfaces.cs" />
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Written by x1nixmzeng for the Cxbx-Reloaded project
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace CxbxDebugger
|
||||
{
|
||||
namespace CheatEngine
|
||||
{
|
||||
public struct State
|
||||
{
|
||||
public uint Value;
|
||||
public bool Activated;
|
||||
public uint RealAddress;
|
||||
};
|
||||
|
||||
public enum Variable
|
||||
{
|
||||
Unknown,
|
||||
Bytes4,
|
||||
}
|
||||
|
||||
public struct CheatEntry
|
||||
{
|
||||
public string ID;
|
||||
public string Description;
|
||||
public State LastState;
|
||||
public uint Color;
|
||||
public Variable VariableType;
|
||||
public string Address;
|
||||
};
|
||||
|
||||
public struct CodeEntry
|
||||
{
|
||||
public string Description;
|
||||
public uint Address;
|
||||
public string ModuleName;
|
||||
public uint ModuleNameOffset;
|
||||
public byte[] Before;
|
||||
public byte[] Actual;
|
||||
public byte[] After;
|
||||
};
|
||||
|
||||
public struct CheatTable
|
||||
{
|
||||
public List<CheatEntry> CheatEntries;
|
||||
public List<CodeEntry> CodeList;
|
||||
};
|
||||
}
|
||||
}
|
|
@ -0,0 +1,300 @@
|
|||
// Written by x1nixmzeng for the Cxbx-Reloaded project
|
||||
//
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
|
||||
namespace CxbxDebugger
|
||||
{
|
||||
namespace CheatEngine
|
||||
{
|
||||
public enum CTReaderResult
|
||||
{
|
||||
Success,
|
||||
LoadFailed,
|
||||
MissingNode,
|
||||
UnsupportedVersion,
|
||||
}
|
||||
|
||||
public class CheatTableReader
|
||||
{
|
||||
CheatTable CTRef;
|
||||
|
||||
public CTReaderResult Load(CheatTable ct, string filename)
|
||||
{
|
||||
XmlDocument doc = new XmlDocument();
|
||||
|
||||
try
|
||||
{
|
||||
doc.Load(filename);
|
||||
}
|
||||
catch
|
||||
{
|
||||
return CTReaderResult.LoadFailed;
|
||||
}
|
||||
|
||||
return ParseDocument(doc);
|
||||
}
|
||||
|
||||
private CTReaderResult ParseDocument(XmlNode root)
|
||||
{
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
if (xnode.Name == "CheatTable")
|
||||
{
|
||||
return ParseCheatTable(xnode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CTReaderResult.MissingNode;
|
||||
}
|
||||
|
||||
private CTReaderResult ParseCheatTable(XmlNode root)
|
||||
{
|
||||
foreach (XmlAttribute attr in root.Attributes)
|
||||
{
|
||||
if (attr.Name == "CheatEngineTableVersion")
|
||||
{
|
||||
if (attr.Value != "21")
|
||||
{
|
||||
return CTReaderResult.UnsupportedVersion;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
switch (xnode.Name)
|
||||
{
|
||||
case "CheatEntries":
|
||||
{
|
||||
ParseCheatEntries(xnode);
|
||||
break;
|
||||
}
|
||||
|
||||
case "CheatCodes":
|
||||
{
|
||||
ParseCheatCodes(xnode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CTReaderResult.Success;
|
||||
}
|
||||
|
||||
private void ParseCheatEntries(XmlNode root)
|
||||
{
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
if (xnode.Name == "CheatEntry")
|
||||
{
|
||||
ParseCheatEntry(xnode);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ParseCheatCodes(XmlNode root)
|
||||
{
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
if (xnode.Name == "CodeEntry")
|
||||
{
|
||||
ParseCodeEntry(xnode);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static uint GetHexNumber(string numeric_string)
|
||||
{
|
||||
uint swap = 0;
|
||||
uint.TryParse(numeric_string, System.Globalization.NumberStyles.HexNumber, null, out swap);
|
||||
return swap;
|
||||
}
|
||||
|
||||
private static uint GetNumber(string numeric_string)
|
||||
{
|
||||
uint swap = 0;
|
||||
uint.TryParse(numeric_string, System.Globalization.NumberStyles.Integer, null, out swap);
|
||||
return swap;
|
||||
}
|
||||
|
||||
private void ParseCheatEntry(XmlNode root)
|
||||
{
|
||||
CheatEntry Entry = new CheatEntry();
|
||||
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
switch (xnode.Name)
|
||||
{
|
||||
case "ID":
|
||||
Entry.ID = xnode.InnerText;
|
||||
break;
|
||||
|
||||
case "Description":
|
||||
Entry.Description = xnode.InnerText;
|
||||
break;
|
||||
|
||||
case "LastState":
|
||||
|
||||
foreach (XmlAttribute attr in xnode.Attributes)
|
||||
{
|
||||
switch (attr.Name)
|
||||
{
|
||||
case "Value":
|
||||
Entry.LastState.Value = GetNumber(attr.Value);
|
||||
break;
|
||||
|
||||
case "Activated":
|
||||
Entry.LastState.Activated = (GetNumber(attr.Value) != 0);
|
||||
break;
|
||||
|
||||
case "RealAddress":
|
||||
Entry.LastState.RealAddress = GetHexNumber(attr.Value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Color":
|
||||
Entry.Color = GetHexNumber(xnode.InnerText);
|
||||
break;
|
||||
|
||||
case "VariableType":
|
||||
|
||||
switch (xnode.InnerText)
|
||||
{
|
||||
case "4 Bytes":
|
||||
Entry.VariableType = Variable.Bytes4;
|
||||
break;
|
||||
|
||||
default:
|
||||
Entry.VariableType = Variable.Unknown;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case "Address":
|
||||
Entry.Address = xnode.InnerText;
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTRef.CheatEntries.Add(Entry);
|
||||
}
|
||||
|
||||
private void ParseCodeEntry(XmlNode root)
|
||||
{
|
||||
CodeEntry Entry = new CodeEntry();
|
||||
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
switch (xnode.Name)
|
||||
{
|
||||
case "Description":
|
||||
Entry.Description = xnode.InnerText;
|
||||
break;
|
||||
|
||||
case "Address":
|
||||
Entry.Address = GetHexNumber(xnode.InnerText);
|
||||
break;
|
||||
|
||||
case "ModuleName":
|
||||
Entry.ModuleName = xnode.InnerText;
|
||||
break;
|
||||
|
||||
case "ModuleNameOffset":
|
||||
Entry.ModuleNameOffset = GetHexNumber(xnode.InnerText);
|
||||
break;
|
||||
|
||||
case "Before":
|
||||
Entry.Before = ParseBytes(xnode);
|
||||
break;
|
||||
|
||||
case "Actual":
|
||||
Entry.Actual = ParseBytes(xnode);
|
||||
break;
|
||||
|
||||
case "After":
|
||||
Entry.After = ParseBytes(xnode);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CTRef.CodeList.Add(Entry);
|
||||
}
|
||||
|
||||
private byte[] ParseBytes(XmlNode root)
|
||||
{
|
||||
List<byte> Bytes = new List<byte>();
|
||||
|
||||
foreach (XmlNode xnode in root.ChildNodes)
|
||||
{
|
||||
switch (xnode.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
if (xnode.Name == "Byte")
|
||||
{
|
||||
uint Value = GetHexNumber(xnode.InnerText);
|
||||
Bytes.Add((byte)(Value & 0xFF));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return Bytes.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue