Sanguine_Studio/jrpcpp/jrpcpp.cpp
2025-12-14 21:37:14 -05:00

1207 lines
42 KiB
C++

#include "jrpcpp.h"
#include "qvariant.h"
JRPCpp::JRPCpp() {}
QString JRPCpp::ToHexString(const QString &aString)
{
return aString.toUtf8().toHex();
}
QByteArray JRPCpp::Push(QByteArray aInArray, char aValue)
{
QByteArray aOutArray = aInArray;
aOutArray.push_back(aValue);
return aOutArray;
}
QByteArray JRPCpp::ToByteArray(const QString &aString)
{
return aString.toUtf8();
}
bool JRPCpp::Connect(const IXboxConsole &aConsole, QString aXboxNameOrIP)
{
IXboxConsole* newCon = nullptr;
if (aXboxNameOrIP == "default")
aXboxNameOrIP = XboxManager::DefaultConsole;
newCon = new XboxManager().OpenConsole(aXboxNameOrIP);
bool Connected = false;
while (!Connected)
{
try
{
connectionId = newCon->OpenConnection(null);
Connected = true;
}
catch (std::exception ex)
{
if (ex.ErrorCode == UIntToInt(0x82DA0100))
{
Console = newCon;
return false;
}
}
}
Console = newCon;
return true;
}
QString JRPCpp::XboxIP(const IXboxConsole &aConsole)
{
QByteArray address = BitConverter.GetBytes(aConsole.IPAddress);
std::reverse(address.constBegin(), address.constEnd());
return QString::fromUtf8(address);
}
ulong JRPCpp::ConvertToUInt64(QVariant aVariant)
{
if (aVariant.canConvert(QMetaType::fromType<bool>()))
return (ulong)aVariant.value<bool>();
else if (aVariant.canConvert(QMetaType::fromType<byte>()))
return (ulong)aVariant.value<byte>();
else if (aVariant.canConvert(QMetaType::fromType<short>()))
return (ulong)aVariant.value<short>();
else if (aVariant.canConvert(QMetaType::fromType<int>()))
return (ulong)aVariant.value<int>();
else if (aVariant.canConvert(QMetaType::fromType<long>()))
return (ulong)aVariant.value<long>();
else if (aVariant.canConvert(QMetaType::fromType<ushort>()))
return (ulong)aVariant.value<ushort>();
else if (aVariant.canConvert(QMetaType::fromType<uint>()))
return (ulong)aVariant.value<uint>();
else if (aVariant.canConvert(QMetaType::fromType<ulong>()))
return (ulong)aVariant.value<ulong>();
else if (aVariant.canConvert(QMetaType::fromType<float>()))
return (ulong)aVariant.value<float>();
else if (aVariant.canConvert(QMetaType::fromType<double>()))
return (ulong)aVariant.value<double>();
return 0UL;
}
bool JRPCpp::isNumericPrimitive(QMetaType t)
{
switch (t.id()) {
case QMetaType::Bool:
case QMetaType::Char:
case QMetaType::SChar:
case QMetaType::UChar:
case QMetaType::Short:
case QMetaType::UShort:
case QMetaType::Int:
case QMetaType::UInt:
case QMetaType::LongLong:
case QMetaType::ULongLong:
case QMetaType::Float:
case QMetaType::Double:
return true;
default:
return false;
}
}
bool JRPCpp::IsValidStructType(QMetaType t)
{
return isNumericPrimitive(t);
}
bool JRPCpp::IsValidReturnType(QMetaType t)
{
return ValidReturnTypes.contains(t);
}
QByteArray JRPCpp::GetMemory(const IXboxConsole &aConsole, uint aAddress, uint aLength)
{
QByteArray result(aLength, Qt::Uninitialized);
uint Out = 0;
aConsole.DebugTarget.GetMemory(Address, Length, Return, out Out);
aConsole.DebugTarget.InvalidateMemoryCache(true, aAddress, Length);
return Return;
}
byte JRPCpp::ReadSByte(const IXboxConsole &aConsole, uint aAddress)
{
return (byte)GetMemory(aConsole, aAddress, 1)[0];
}
byte JRPCpp::ReadByte(const IXboxConsole &aConsole, uint aAddress)
{
return GetMemory(aConsole, aAddress, 1)[0];
}
bool JRPCpp::ReadBool(const IXboxConsole &aConsole, uint aAddress)
{
return GetMemory(aConsole, aAddress, 1)[0] != 0;
}
QVector<qint64> JRPCpp::ReadInt64(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
QVector<qint64> result(aArraySize);
QByteArray buff = GetMemory(aConsole, aAddress, aArraySize * 8);
ReverseBytes(buff, 8);
for (int i = 0; i < aArraySize; i++)
{
QByteArray intBuff = buff.mid(i * 8, 8);
result[i] = intBuff.toInt();
}
return result;
}
void JRPCpp::WriteBool(const IXboxConsole &aConsole, uint aAddress, QVector<bool> aValue)
{
QByteArray result;
for(int i = 0; i < aValue.size(); i++)
{
result.push_back((char)(aValue[i] ? 1 : 0));
}
SetMemory(aConsole, aAddress, result);
}
void JRPCpp::WriteFloat(const IXboxConsole &aConsole, uint aAddress, float aValue)
{
QByteArray buff = QString::number(aValue).toUtf8();
Array.Reverse(buff);
SetMemory(aConsole, aAddress, buff);
}
void JRPCpp::WriteFloat(const IXboxConsole &aConsole, uint aAddress, QVector<float> aValue)
{
QByteArray buff(aValue.size() * 4);
for (int i = 0; i < aValue.size(); i++)
{
BitConverter.GetBytes(aValue[i]).CopyTo(buff, i * 4);
}
ReverseBytes(buff, 4);
SetMemory(aConsole, aAddress, buff);
}
void JRPCpp::WriteInt16(const IXboxConsole &aConsole, uint aAddress, short aValue)
{
QByteArray Buff = BitConverter.GetBytes(Value);
ReverseBytes(Buff, 2);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteInt16(const IXboxConsole &aConsole, uint aAddress, QVector<short> aValue)
{
QByteArray Buff = new byte[Value.Length * 2];
for (int i = 0; i < aValue.Length; i++)
BitConverter.GetBytes(Value[i]).CopyTo(Buff, i * 2);
ReverseBytes(Buff, 2);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteUInt16(const IXboxConsole &aConsole, uint aAddress, ushort aValue)
{
QByteArray Buff = BitConverter.GetBytes(Value);
ReverseBytes(Buff, 2);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteUInt16(const IXboxConsole &aConsole, uint aAddress, QVector<short> aValue)
{
QByteArray Buff = new byte[Value.Length * 2];
for (int i = 0; i < aValue.Length; i++)
BitConverter.GetBytes(Value[i]).CopyTo(Buff, i * 2);
ReverseBytes(Buff, 2);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteInt32(const IXboxConsole &aConsole, uint aAddress, int aValue)
{
QByteArray Buff = BitConverter.GetBytes(Value);
ReverseBytes(Buff, 4);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteInt32(const IXboxConsole &aConsole, uint aAddress, QVector<int> aValue)
{
QByteArray Buff = new byte[Value.Length * 4];
for (int i = 0; i < aValue.Length; i++)
BitConverter.GetBytes(Value[i]).CopyTo(Buff, i * 4);
ReverseBytes(Buff, 4);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteUInt32(const IXboxConsole &aConsole, uint aAddress, uint aValue)
{
QByteArray Buff = BitConverter.GetBytes(Value);
ReverseBytes(Buff, 4);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteUInt32(const IXboxConsole &aConsole, uint aAddress, QVector<uint> aValue)
{
QByteArray Buff = new byte[Value.Length * 4];
for (int i = 0; i < aValue.Length; i++)
BitConverter.GetBytes(Value[i]).CopyTo(Buff, i * 4);
ReverseBytes(Buff, 4);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteInt64(const IXboxConsole &aConsole, uint aAddress, long aValue)
{
QByteArray Buff = BitConverter.GetBytes(Value);
ReverseBytes(Buff, 8);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteInt64(const IXboxConsole &aConsole, uint aAddress, QVector<long> aValue)
{
QByteArray Buff = new byte[Value.Length * 8];
for (int i = 0; i < aValue.Length; i++)
BitConverter.GetBytes(Value[i]).CopyTo(Buff, i * 8);
ReverseBytes(Buff, 8);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteUInt64(const IXboxConsole &aConsole, uint aAddress, unsigned long aValue)
{
QByteArray Buff = BitConverter.GetBytes(Value);
ReverseBytes(Buff, 8);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteUInt64(const IXboxConsole &aConsole, uint aAddress, QVector<unsigned long> aValue)
{
QByteArray Buff = new byte[Value.Length * 8];
for (int i = 0; i < aValue.Length; i++)
BitConverter.GetBytes(Value[i]).CopyTo(Buff, i * 8);
ReverseBytes(Buff, 8);
SetMemory(aConsole, aAddress, Buff);
}
void JRPCpp::WriteString(const IXboxConsole &aConsole, uint aAddress, QString String)
{
QByteArray bValue = new byte[0];
foreach(byte b in String)
bValue.Push(out bValue, b);
bValue.Push(out bValue, 0);
SetMemory(aConsole, aAddress, bValue);
}
uint JRPCpp::ResolveFunction(const IXboxConsole &aConsole, QString aModuleName, uint aOrdinal)
{
QString cmd = "consolefeatures ver=" + JRPCVersion + " type=9 params=\"A\\0\\A\\2\\" +
JRPC.String + "/" + ModuleName.Length + "\\" + ModuleName.ToHexString() + "\\" +
JRPC.Int + "\\" + aOrdinal + "\\\"",
Responce = SendCommand(aConsole, cmd);
return uint.Parse(Responce.SubQString(Responce.find(" ")+1), System.Globalization.NumberStyles.HexNumber);
}
QString JRPCpp::GetCPUKey(const IXboxConsole &aConsole)
{
QString cmd = QString("consolefeatures ver=%1 type=10 params=\"A\\0\\A\\0\\\"").arg(JRPCVersion);
QString response = SendCommand(aConsole, cmd);
return response.mid(response.indexOf(" ") + 1);
}
void JRPCpp::ShutDownConsole(const IXboxConsole &aConsole)
{
QString cmd = QString("consolefeatures ver=%1 type=11 params=\"A\\0\\A\\0\\\"").arg(JRPCVersion);
SendCommand(aConsole, cmd);
}
QByteArray JRPCpp::WCHAR(QString String)
{
QByteArray Bytes = new byte[String.Length * 2 + 2];
int i = 1;
foreach (byte b in String)
{
Bytes[i] = b;
i += 2;
}
return Bytes;
}
QByteArray JRPCpp::ToWCHAR(QString String)
{
return WCHAR(String);
}
uint JRPCpp::GetKernalVersion(const IXboxConsole &aConsole)
{
QString cmd = QString("consolefeatures ver=%1 type=13 params=\"A\\0\\A\\0\\\"").arg(JRPCVersion);
QString response = SendCommand(aConsole, cmd);
bool ok;
QString uintStr = response.mid(response.indexOf(" ") + 1);
uint result = uintStr.toUInt(&ok);
if (!ok)
{
qDebug() << "ERROR: Failed to convert to UInt str" << uintStr;
return 0;
}
return result;
}
void JRPCpp::SetLeds(const IXboxConsole &aConsole, LEDState aTopLeft, LEDState aTopRight, LEDState aBottomLeft, LEDState aBottomRight)
{
QString cmd = QString("consolefeatures ver=%1 type=14 params=\"A\\0\\A\\4\\%2\\%3\\%2\\%4\\%2\\%5\\%2\\%6\\\"")
.arg(JRPCVersion)
.arg(JRPCpp::Int)
.arg(aTopLeft)
.arg(aTopRight)
.arg(aBottomLeft)
.arg(aBottomRight);
SendCommand(aConsole, cmd);
}
void JRPCpp::XNotify(const IXboxConsole &aConsole, QString aText)
{
XNotify(aConsole, XNotifyLogo::FLASHING_XBOX_CONSOLE, aText);
}
uint JRPCpp::GetTemperature(const IXboxConsole &aConsole, TemperatureType TemperatureType)
{
QString cmd = QString("consolefeatures ver=%1 type=15 params=\"A\\0\\A\\1\\%2\\%3\\\"")
.arg(JRPCVersion)
.arg(JRPCpp::Int)
.arg(TemperatureType);
QString response = SendCommand(aConsole, cmd);
bool ok;
QString uintStr = response.mid(response.indexOf(" ") + 1);
uint result = uintStr.toUInt(&ok);
if (!ok)
{
qDebug() << "ERROR: Failed to convert to UInt str" << uintStr;
return 0;
}
return result;
}
void JRPCpp::XNotify(const IXboxConsole &aConsole, XNotifyLogo aType, QString aText)
{
QString cmd = QString("consolefeatures ver=%1 type=12 params=\"A\\0\\A\\2\\%2\\%3\\\"")
.arg(JRPCVersion)
.arg(JRPCpp::String)
.arg(aText.length())
.arg(aText.toUtf8().toHex())
.arg(aType);
SendCommand(aConsole, cmd);
}
uint JRPCpp::XamGetCurrentTitleId(const IXboxConsole &aConsole)
{
QString cmd = QString("consolefeatures ver=%1 type=16 params=\"A\\0\\A\\0\\\"").arg(JRPCVersion);
QString response = SendCommand(aConsole, cmd);
bool ok;
QString uintStr = response.mid(response.indexOf(" ") + 1);
uint result = uintStr.toUInt(&ok);
if (!ok)
{
qDebug() << "ERROR: Failed to convert to UInt str" << uintStr;
return 0;
}
return result;
}
QString JRPCpp::ConsoleType(const IXboxConsole &aConsole)
{
QString cmd = QString("consolefeatures ver=%1 type=17 params=\"A\\0\\A\\0\\\"")
.arg(JRPCVersion);
QString response = SendCommand(aConsole, cmd);
return response.mid(response.indexOf(" ") + 1);
}
void JRPCpp::constantMemorySet(const IXboxConsole &aConsole, uint aAddress, uint aValue)
{
constantMemorySetting(aConsole, aAddress, aValue, false, 0, false, 0);
}
void JRPCpp::constantMemorySet(const IXboxConsole &aConsole, uint aAddress, uint aValue, uint TitleID)
{
constantMemorySetting(aConsole, aAddress, aValue, false, 0, true, TitleID);
}
void JRPCpp::constantMemorySet(const IXboxConsole &aConsole, uint aAddress, uint aValue, uint IfValue, uint TitleID)
{
constantMemorySetting(aConsole, aAddress, aValue, true, IfValue, true, TitleID);
}
void JRPCpp::constantMemorySetting(
const IXboxConsole& aConsole,
uint aAddress,
uint aValue,
bool useIfValue,
uint IfValue,
bool usetitleID,
uint TitleID)
{
QString cmd = QString("consolefeatures ver=%1 type=18 params=\"A\\%2\\A\\5\\\"%3\\%4\\%3\\%5\\%3\\%6\\%3\\%7\\%3\\%8\\\"")
.arg(JRPCVersion)
.arg(aAddress)
.arg(JRPCpp::Int)
.arg(UIntToInt(aValue))
.arg((useIfValue ? 1 : 0))
.arg(IfValue)
.arg((usetitleID ? 1 : 0))
.arg(UIntToInt(TitleID));
SendCommand(aConsole, cmd);
}
void JRPCpp::CallVoid(const IXboxConsole &aConsole, uint aAddress, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, true, JRPCpp::Void, QMetaType::fromType<void>(), nullptr, 0, aAddress, 0, false, aArguments);
}
void JRPCpp::CallVoid(const IXboxConsole &aConsole, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, true, JRPCpp::Void, QMetaType::fromType<void>(), aModule, aOrdinal, 0, 0, false, aArguments);
}
void JRPCpp::CallVoid(const IXboxConsole &aConsole, ThreadType aType, uint aAddress, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, aType == ThreadType::SystemType, JRPCpp::Void, QMetaType::fromType<void>(), nullptr, 0, aAddress, 0, false, aArguments);
}
void JRPCpp::CallVoid(const IXboxConsole &aConsole, ThreadType aType, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, aType == ThreadType::SystemType, JRPCpp::Void, QMetaType::fromType<void>(), aModule, aOrdinal, 0, 0, false, aArguments);
}
template <typename T>
QVector<T> JRPCpp::ArrayReturn(const IXboxConsole &aConsole, uint aAddress, uint Size)
{
if(Size == 0)
return new T[1];
QMetaType type = QMetaType::fromType<T>();
QVariant result;
if (type == QMetaType::fromType<short>())
result.fromValue(ReadInt16(aConsole, aAddress, Size));
if (type == QMetaType::fromType<ushort>())
result.fromValue(ReadUInt16(aConsole, aAddress, Size));
if (type == QMetaType::fromType<int>())
result.fromValue(ReadInt32(aConsole, aAddress, Size));
if (type == QMetaType::fromType<uint>())
result.fromValue(ReadUInt32(aConsole, aAddress, Size));
if (type == QMetaType::fromType<long>())
result.fromValue(ReadInt64(aConsole, aAddress, Size));
if (type == QMetaType::fromType<ulong>())
result.fromValue(ReadUInt64(aConsole, aAddress, Size));
if (type == QMetaType::fromType<float>())
result.fromValue(ReadFloat(aConsole, aAddress, Size));
if (type == QMetaType::fromType<byte>())
result.fromValue(GetMemory(aConsole, aAddress, Size));
return (T[])result;
}
QString JRPCpp::CallString(const IXboxConsole &aConsole, uint aAddress, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, true, JRPCpp::String, QMetaType::fromType<QString>(), nullptr, 0, aAddress, 0, false, aArguments)
.toString();
}
QString JRPCpp::CallString(const IXboxConsole &aConsole, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, true, JRPCpp::String, QMetaType::fromType<QString>(), aModule, aOrdinal, 0, 0, false, aArguments)
.toString();
}
QString JRPCpp::CallString(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, Type == ThreadType::SystemType, JRPCpp::String, QMetaType::fromType<QString>(), nullptr, 0, aAddress, 0, false, aArguments)
.toString();
}
QString JRPCpp::CallString(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, Type == ThreadType::SystemType, JRPCpp::String, QMetaType::fromType<QString>(), aModule, aOrdinal, 0, 0, false, aArguments)
.toString();
}
int JRPCpp::UIntToInt(uint aValue)
{
QByteArray array = BitConverter.GetBytes(Value);
return BitConverter.ToInt32(array, 0);
}
QByteArray JRPCpp::IntArrayToByte(QVector<int> iArray)
{
QByteArray Bytes = new byte[iArray.Length * 4];
for (int i = 0, q = 0; i < iArray.Length; i++, q += 4)
for (int w = 0; w < 4; w++)
Bytes[q + w] = BitConverter.GetBytes(iArray[i])[w];
return Bytes;
}
void JRPCpp::CallVMVoid(const IXboxConsole &aConsole, uint aAddress, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, true, JRPCpp::Void, QMetaType::fromType<void>(), nullptr, 0, aAddress, 0, true, aArguments);
}
void JRPCpp::CallVMVoid(const IXboxConsole &aConsole, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, true, JRPCpp::Void, QMetaType::fromType<void>(), aModule, aOrdinal, 0, 0, true, aArguments);
}
void JRPCpp::CallVMVoid(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, Type == ThreadType::SystemType, JRPCpp::Void, QMetaType::fromType<void>(), nullptr, 0, aAddress, 0, true, aArguments);
}
void JRPCpp::CallVMVoid(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
CallArgs(aConsole, Type == ThreadType::SystemType, JRPCpp::Void, QMetaType::fromType<void>(), aModule, aOrdinal, 0, 0, true, aArguments);
}
template <typename T>
QVector<T> CallVMArray(const IXboxConsole &aConsole, uint aAddress, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, true, TypeToType(true), QMetaType::fromType<T>(), nullptr, 0, aAddress, aArraySize, true, aArguments);
}
template <typename T>
QVector<T> CallVMArray(const IXboxConsole &aConsole, QString aModule, int aOrdinal, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, true, TypeToType(true), QMetaType::fromType<T>(), aModule, aOrdinal, 0, aArraySize, true, aArguments);
}
template <typename T>
QVector<T> CallVMArray(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(true), QMetaType::fromType<T>(), nullptr, 0, aAddress, aArraySize, true, aArguments);
}
template <typename T>
QVector<T> CallVMArray(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(true), QMetaType::fromType<T>(), aModule, aOrdinal, 0, aArraySize, true, aArguments);
}
QString JRPCpp::CallVMString(const IXboxConsole &aConsole, uint aAddress, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, true, JRPCpp::String, QMetaType::fromType<QString>(), nullptr, 0, aAddress, 0, true, aArguments).toString();
}
QString JRPCpp::CallVMString(const IXboxConsole &aConsole, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, true, JRPCpp::String, QMetaType::fromType<QString>(), aModule, aOrdinal, 0, 0, true, aArguments).toString();
}
QString JRPCpp::CallVMString(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, Type == ThreadType::SystemType, JRPCpp::String, QMetaType::fromType<QString>(), nullptr, 0, aAddress, 0, true, aArguments)
.toString();
}
QString JRPCpp::CallVMString(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return CallArgs(aConsole, Type == ThreadType::SystemType, JRPCpp::String, QMetaType::fromType<QString>(), aModule, aOrdinal, 0, 0, true, aArguments)
.toString();
}
QString JRPCpp::SendCommand(const IXboxConsole &aConsole, QString Command)
{
QString response;
if (connectionId == 0)
throw std::exception("IXboxConsole argument did not connect using JRPC's connect function.");
try
{
aConsole.SendTextCommand(connectionId, Command, out Responce);
if (response.contains("error="))
{
//throw std::exception(response.mid(11));
}
if (response.contains("DEBUG"))
{
throw std::exception("JRPC is not installed on the current console");
}
}
catch (COMException ex)
{
// if (ex.ErrorCode == UIntToInt(0x82DA0007))
// throw std::exception("JRPC is not installed on the current console");
// else
throw ex;
}
return response;
}
QVariant JRPCpp::CallArgs(const IXboxConsole &aConsole, bool aSystemThread, uint aType, QMetaType t, QString aModule, int aOrdinal, uint aAddress, uint aArraySize, bool VM, const QVector<QVariant> &aArguments)
{
if (!JRPCpp::IsValidReturnType(t))
{
qDebug() << "ERROR: Invalid type " << t.name() << "\nJRPC only supports: bool, byte, short, int, long, ushort, uint, unsigned long, float, double";
return QVariant();
}
else
{
aConsole.ConnectTimeout = aConsole.ConversationTimeout = 4000000;//set to 400 secounds incase there is a little delay in recving
QString SendCMD = "";
uint NumOfArgs = 0;
foreach (QVariant obj, aArguments)
{
bool Done = false;
if (obj.canConvert(QMetaType::fromType<uint>()))
{
SendCMD += QString("%1\\%2\\")
.arg(JRPCpp::Int)
.arg(obj.value<uint>());
NumOfArgs += 1;
Done = true;
}
if (obj.canConvert(QMetaType::fromType<int>())
|| obj.canConvert(QMetaType::fromType<bool>())
|| obj.canConvert(QMetaType::fromType<byte>()))
{
if (obj.canConvert(QMetaType::fromType<byte>()))
{
SendCMD += QString("%1\\%2\\")
.arg(JRPCpp::Int)
.arg(obj.value<byte>());
}
else
{
SendCMD += QString("%1\\%2\\")
.arg(JRPCpp::Int)
.arg(obj.value<qint32>());
}
NumOfArgs += 1;
Done = true;
}
else if (obj.canConvert(QMetaType::fromType<QVector<int>>())
|| obj.canConvert(QMetaType::fromType<QVector<uint>>()))
{
if (!VM)
{
QByteArray array = IntArrayToByte(obj.value<QVector<int>>());
SendCMD += QString("%1/%2\\").arg(JRPCpp::ByteArray).arg(array.size());
for (int i = 0; i < array.size(); i++)
SendCMD += QString::number(array[i]);
SendCMD += "\\";
NumOfArgs += 1;
}
else
{
bool isInt = obj.canConvert(QMetaType::fromType<QVector<int>>());
int len;
if(isInt)
{
QVector<int> iarray = obj.value<QVector<int>>();
len = iarray.size();
}
else
{
QVector<uint> iarray = obj.value<QVector<uint>>();
len = iarray.size();
}
QVector<int> Iarray(len);
for(int i = 0; i < len; i++)
{
if(isInt)
{
QVector<int> tiarray = obj.value<QVector<int>>();
Iarray[i] = tiarray[i];
}
else
{
QVector<uint> tiarray = obj.value<QVector<uint>>();
Iarray[i] = UIntToInt(tiarray[i]);
}
SendCMD += QString("%1\\%2\\").arg(JRPCpp::Int).arg(Iarray[i]);
NumOfArgs += 1;
}
}
Done = true;
}
else if (obj.canConvert(QMetaType::fromType<QString>()))
{
QString str = obj.toString();
SendCMD += QString("%1/%2\\%3\\").arg(JRPCpp::ByteArray).arg(str.size()).arg(obj.toString().toUtf8().toHex());
NumOfArgs += 1;
Done = true;
}
else if (obj.canConvert(QMetaType::fromType<double>()))
{
double d = obj.toDouble();
SendCMD += QString("%1\\%2\\").arg(JRPCpp::Float).arg(d);
NumOfArgs += 1;
Done = true;
}
else if (obj.canConvert(QMetaType::fromType<float>()))
{
float fl = obj.toFloat();
SendCMD += QString("%1\\%2\\").arg(JRPCpp::Float).arg(fl);
NumOfArgs += 1;
Done = true;
}
else if (obj.canConvert(QMetaType::fromType<QVector<float>>()))
{
QVector<float> floatArray = obj.value<QVector<float>>();
if (!VM)
{
SendCMD += QString("%1/%2\\").arg(JRPCpp::ByteArray).arg(floatArray.size() * 4);
for (int i = 0; i < floatArray.size(); i++)
{
QByteArray bytes = QString::number(floatArray[i]).toUtf8();
Array.Reverse(bytes);
for (int q = 0; q < 4; q++)
SendCMD += QString::number(bytes[q]);
}
SendCMD += "\\";
NumOfArgs += 1;
}
else
{
for (int i = 0; i < floatArray.size(); i++)
{
SendCMD += QString("%1\\%2\\").arg(JRPCpp::Float).arg(floatArray[i]);
NumOfArgs += 1;
}
}
Done = true;
}
else if (obj is QByteArray)
{
QByteArray ByteArray = (QByteArray)obj;
SendCMD += JRPCpp::ByteArray.ToString() + "/" + ByteArray.Length + "\\";
for (int i = 0; i < ByteArray.Length; i++)
SendCMD += ByteArray[i].ToString("X2");
SendCMD += "\\";
NumOfArgs += 1;
Done = true;
}
if (!Done)
{
SendCMD += JRPCpp::Uint64.ToString() + "\\" + ConvertToUInt64(obj).ToString()+ "\\";
NumOfArgs += 1;
}
}
SendCMD += "\"";
QString startSendCMD = "consolefeatures ver=" + JRPCVersion + " type=" + Type + (SystemThread ? " system" : "") +
(module != null ? " module=\"" + module + "\" ord=" + aOrdinal : "") +
(VM ? " VM" : "") +
" as=" + aArraySize + " params=\"A\\" + Address.ToString("X") + "\\A\\" + NumOfArgs + "\\" + SendCMD,
Responce;
if (NumOfArgs > 37)
throw new Exception("Can not use more than 37 paramaters in a call");
Responce = SendCommand(aConsole, startSendCMD);
QString Find = "buf_addr=";
while (Responce.Contains(Find))
{
System.Threading.Thread.Sleep(250);
uint aAddress = uint.Parse(Responce.SubQString(Responce.find(Find) + Find.Length), System.Globalization.NumberStyles.HexNumber);
Responce = SendCommand(aConsole, "consolefeatures " + Find + "0x" + address.ToString("X"));
}
console.ConversationTimeout = 2000;//reset the timeout
console.ConnectTimeout = 5000;
switch(Type)
{
case 1:/*Int*/
uint uVal = uint.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
if(t == typeof(uint))
return uVal;
if (t == typeof(int))
return UIntToInt(uVal);
if (t == typeof(short))
return short.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
if (t == typeof(ushort))
return ushort.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
break;
case 2:/*String*/
QString sString = Responce.SubQString(Responce.find(" ") + 1);
if (t == QMetaType::fromType<QString>())
return sString;
if (t == typeof(char[]))
return sString.ToCharArray();
break;
case 3:/*Float*/
if (t == typeof(double))
return double.Parse(Responce.SubQString(Responce.find(" ") + 1));
if (t == typeof(float))
return float.Parse(Responce.SubQString(Responce.find(" ") + 1));;
break;
case 4:/*Byte*/
byte bByte = byte.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
if (t == typeof(byte))
return bByte;
if (t == typeof(char))
return (char)bByte;
break;
case 8:/*UInt64*/
if (t == typeof(long))
return long.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
if (t == typeof(unsigned long))
return unsigned long.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
break;
}
if (Type == 5)//IntArray
{
QString String = Responce.SubQString(Responce.find(" ") + 1);
int Tmp = 0;
QString Temp = "";
QVector<uint> Uarray = new uint[8];
foreach (char Char1 in String)
{
if (Char1 != ',' && Char1 != ';')
Temp += Char1.ToString();
else
{
Uarray[Tmp] = uint.Parse(Temp, System.Globalization.NumberStyles.HexNumber);
Tmp += 1;
Temp = "";
}
if (Char1 == ';')
break;
}
return Uarray;
}
if (Type == 6)//FloatArray
{
QString String = Responce.SubQString(Responce.find(" ") + 1);
int Tmp = 0;
QString Temp = "";
QVector<float> Farray = new float[ArraySize];
foreach (char Char1 in String)
{
if (Char1 != ',' && Char1 != ';')
Temp += Char1.ToString();
else
{
Farray[Tmp] = float.Parse(Temp);
Tmp += 1;
Temp = "";
}
if (Char1 == ';')
break;
}
return Farray;
}
if (Type == 7)//ByteArray
{
QString String = Responce.SubQString(Responce.find(" ") + 1);
int Tmp = 0;
QString Temp = "";
QByteArray Barray = new byte[ArraySize];
foreach (char Char1 in String)
{
if (Char1 != ',' && Char1 != ';')
Temp += Char1.ToString();
else
{
Barray[Tmp] = byte.Parse(Temp);
Tmp += 1;
Temp = "";
}
if (Char1 == ';')
break;
}
return Barray;
}
if (Type == JRPCpp::Uint64Array)
{
QString String = Responce.SubQString(Responce.find(" ") + 1);
int Tmp = 0;
QString Temp = "";
QVector<unsigned long> unsigned longArray = new unsigned long[ArraySize];
foreach (char Char1 in String)
{
if (Char1 != ',' && Char1 != ';')
Temp += Char1.ToString();
else
{
unsigned longArray[Tmp] =unsigned long.Parse(Temp);
Tmp += 1;
Temp = "";
}
if (Char1 == ';')
break;
}
if(t == typeof(unsigned long))
return unsigned longArray;
else if (t == typeof(long))
{
QVector<long> longArray = new long[ArraySize];
for (int i = 0; i < aArraySize; i++)
longArray[i] = BitConverter.ToInt64(BitConverter.GetBytes(unsigned longArray[i]), 0);
return longArray;
}
}
if (Type == Void)
return 0;
return unsigned long.Parse(Responce.SubQString(Responce.find(" ") + 1), System.Globalization.NumberStyles.HexNumber);
}
}
void JRPCpp::ReverseBytes(QByteArray buffer, int groupSize)
{
if (buffer.Length % groupSize != 0)
throw new ArgumentException("Group size must be a multiple of the buffer length", "groupSize");
int num1 = 0;
while (num1 < buffer.Length)
{
int index1 = num1;
for (int index2 = num1 + groupSize - 1; index1 < index2; --index2)
{
byte num2 = buffer[index1];
buffer[index1] = buffer[index2];
buffer[index2] = num2;
++index1;
}
num1 += groupSize;
}
}
float JRPCpp::ReadFloat(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray buff = GetMemory(aConsole, aAddress, 4);
ReverseBytes(buff, 4);
return buff.toFloat();
}
QVector<float> JRPCpp::ReadFloat(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
QVector<float> result(aArraySize);
QByteArray buff = GetMemory(aConsole, aAddress, aArraySize * 4);
ReverseBytes(buff, 4);
for (int i = 0; i < aArraySize; i++)
result[i] = buff.mid(i * 4, 4).toFloat();
return result;
}
qint16 JRPCpp::ReadInt16(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray buff = GetMemory(aConsole, aAddress, 2);
ReverseBytes(buff, 2);
return buff.toInt();
}
QVector<qint16> JRPCpp::ReadInt16(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
QVector<qint16> result(aArraySize);
QByteArray buff = GetMemory(aConsole, aAddress, aArraySize * 2);
ReverseBytes(buff, 2);
for (int i = 0; i < aArraySize; i++)
result[i] = buff.mid(i * 2, 2).toInt();
return result;
}
ushort JRPCpp::ReadUInt16(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray buff = GetMemory(aConsole, aAddress, 2);
ReverseBytes(buff, 2);
return buff.toUInt();
}
void JRPCpp::WriteByte(const IXboxConsole &aConsole, uint aAddress, byte aValue)
{
SetMemory(aConsole, aAddress, new byte[1] { aValue });
}
QVector<quint16> JRPCpp::ReadUInt16(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
ushort[] Return = new ushort[ArraySize];
QByteArray Buff = GetMemory(aConsole, aAddress, aArraySize * 2);
ReverseBytes(Buff, 2);
for (int i = 0; i < aArraySize; i++)
Return[i] = BitConverter.ToUInt16(Buff, i * 2);
return Return;
}
int JRPCpp::ReadInt32(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray Buff = GetMemory(aConsole, aAddress, 4);
ReverseBytes(Buff, 4);
return BitConverter.ToInt32(Buff, 0);
}
QVector<qint32> JRPCpp::ReadInt32(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
int[] Return = new int[ArraySize];
QByteArray Buff = GetMemory(aConsole, aAddress, aArraySize * 4);
ReverseBytes(Buff, 4);
for (int i = 0; i < aArraySize; i++)
Return[i] = BitConverter.ToInt32(Buff, i * 4);
return Return;
}
uint JRPCpp::ReadUInt32(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray Buff = GetMemory(aConsole, aAddress, 4);
ReverseBytes(Buff, 4);
return BitConverter.ToUInt32(Buff, 0);
}
QVector<quint32> JRPCpp::ReadUInt32(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
uint[] Return = new uint[ArraySize];
QByteArray Buff = GetMemory(aConsole, aAddress, aArraySize * 4);
ReverseBytes(Buff, 4);
for (int i = 0; i < aArraySize; i++)
Return[i] = BitConverter.ToUInt32(Buff, i * 4);
return Return;
}
qint64 JRPCpp::ReadInt64(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray buff = GetMemory(aConsole, aAddress, 8);
ReverseBytes(buff, 8);
return buff.toInt();
}
quint64 JRPCpp::ReadUInt64(const IXboxConsole &aConsole, uint aAddress)
{
QByteArray buff = GetMemory(aConsole, aAddress, 8);
ReverseBytes(buff, 8);
return buff.toUInt();
}
QVector<quint64> JRPCpp::ReadUInt64(const IXboxConsole &aConsole, uint aAddress, uint aArraySize)
{
QVector<quint64>result(aArraySize);
QByteArray buff = GetMemory(aConsole, aAddress, aArraySize * 8);
ReverseBytes(buff, 8);
for (int i = 0; i < aArraySize; i++)
result[i] = buff.mid(i * 8, 8).toUInt();
return result;
}
QString JRPCpp::ReadString(const IXboxConsole &aConsole, uint aAddress, uint size)
{
QByteArray buff = GetMemory(aConsole, aAddress, size);
return QString::fromUtf8(buff);
}
void JRPCpp::SetMemory(const IXboxConsole &aConsole, uint aAddress, QByteArray aData)
{
uint out;
aConsole.DebugTarget.SetMemory(aAddress, (uint)aData.size(), aData, &out);
}
void JRPCpp::WriteSByte(const IXboxConsole &aConsole, uint aAddress, byte aValue)
{
SetMemory(aConsole, aAddress, QString::number(aValue).toUtf8());
}
void JRPCpp::WriteSByte(const IXboxConsole &aConsole, uint aAddress, QByteArray aValue)
{
QByteArray bytes;
foreach (byte b, aValue)
bytes.push_back(b);
SetMemory(aConsole, aAddress, bytes);
}
void JRPCpp::WriteByte(const IXboxConsole &aConsole, uint aAddress, byte aValue)
{
SetMemory(aConsole, aAddress, QString::number(aValue).toUtf8());
}
void JRPCpp::WriteByte(const IXboxConsole &aConsole, uint aAddress, QByteArray aValue)
{
SetMemory(aConsole, aAddress, aValue);
}
void JRPCpp::WriteBool(const IXboxConsole &aConsole, uint aAddress, bool aValue)
{
SetMemory(aConsole, aAddress, QString::number((aValue ? 1 : 0)).toUtf8());
}
template<typename T>
T JRPCpp::Call(const IXboxConsole &aConsole, uint aAddress, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, true, TypeToType(false), QMetaType::fromType<T>(), nullptr, 0, aAddress, 0, false, aArguments);
}
template<typename T>
T JRPCpp::Call(const IXboxConsole &aConsole, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, true, TypeToType(false), QMetaType::fromType<T>(), aModule, aOrdinal, 0, 0, false, aArguments);
}
template<typename T>
T JRPCpp::Call(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(false), QMetaType::fromType<T>(), nullptr, 0, aAddress, 0, false, aArguments);
}
template<typename T>
T JRPCpp::Call(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(false), QMetaType::fromType<T>(), aModule, aOrdinal, 0, 0, false, aArguments);
}
template<typename T>
QVector<T> JRPCpp::CallArray(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(true), QMetaType::fromType<T>(), aModule, aOrdinal, 0, aArraySize, false, aArguments);
}
template<typename T>
QVector<T> JRPCpp::CallArray(const IXboxConsole &aConsole, uint aAddress, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, true, TypeToType(true), QMetaType::fromType<T>(), nullptr, 0, aAddress, aArraySize, false, aArguments);
}
template<typename T>
QVector<T> JRPCpp::CallArray(const IXboxConsole &aConsole, QString aModule, int aOrdinal, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, true, TypeToType(true), QMetaType::fromType<T>(), aModule, aOrdinal, 0, aArraySize, false, aArguments);
}
template<typename T>
QVector<T> JRPCpp::CallArray(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, uint aArraySize, const QVector<QVariant> &aArguments)
{
if (aArraySize == 0)
return new T[1];
return (T[])CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(true), QMetaType::fromType<T>(), nullptr, 0, aAddress, aArraySize, false, aArguments);
}
template<typename T>
T JRPCpp::CallVM(const IXboxConsole &aConsole, uint aAddress, QVector<QVariant> aArguments)
{
return (T)CallArgs(aConsole, true, TypeToType(false), QMetaType::fromType<T>(), nullptr, 0, aAddress, 0, true, aArguments);
}
template<typename T>
T JRPCpp::CallVM(const IXboxConsole &aConsole, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, true, TypeToType(false), QMetaType::fromType<T>(), aModule, aOrdinal, 0, 0, true, aArguments);
}
template<typename T>
T JRPCpp::CallVM(const IXboxConsole &aConsole, ThreadType Type, uint aAddress, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(false), QMetaType::fromType<T>(), nullptr, 0, aAddress, 0, true, aArguments);
}
template<typename T>
T JRPCpp::CallVM(const IXboxConsole &aConsole, ThreadType Type, QString aModule, int aOrdinal, const QVector<QVariant> &aArguments)
{
return (T)CallArgs(aConsole, Type == ThreadType::SystemType, TypeToType(false), QMetaType::fromType<T>(), aModule, aOrdinal, 0, 0, true, aArguments);
}