#region DbcUtils
internal static class DbcUtils
{
private const uint WOW_USE_SPELL_UNPACK = 0xC775D0;
public static void GetLocalizedRow(uint clientDb, int recordId, out IntPtr buffer)
{
clientDb = (uint)(clientDb - 0x18);
var header = Memory.ReadStruct<DBC.WoWClientDb>(clientDb);
buffer = IntPtr.Zero;
if (recordId >= header.MinIndex && recordId <= header.MaxIndex)
{
IntPtr lpRow = Memory.Read<IntPtr>((uint)(header.Rows + (4 * (recordId - header.MinIndex))));
if (Memory.Read<byte>((uint)WOW_USE_SPELL_UNPACK) == 1)
{
UnpackSpellDb(lpRow, 0x2C0u, out buffer);
}
else
{
byte[] data = Native.ReadBytes((uint)lpRow, 0x2C0);
buffer = Marshal.AllocHGlobal(0x2C0);
Marshal.Copy(data, 0, buffer, 0x2C0);
}
}
}
private static void UnpackSpellDb(IntPtr source, uint size, out IntPtr buffer)
{
// This function is taken directly from WoW. It includes lots of Marshal usage, and some other stuff.
// So if you don't understand it, tough shit. :D
// Way too much allocated; but oh well.
byte[] byteBuffer = new byte[0x5000];
// *outBuffer = *source;
byteBuffer[0] = Memory.Read<byte>((uint)source);
// currentAddress = outBuffer + 1;
int currentAddress = 1;
uint i;
// for ( i = (char *)source + 1; currentAddress < endAddress; ++i )
for (i = (uint)(source.ToInt32() + 1); currentAddress < size; ++i)
{
// *currentAddress++ = *i;
byteBuffer[currentAddress++] = Memory.Read<byte>((uint)i);
//currentAddress++;
// if (*i == *(i -1))
byte atI = Memory.Read<byte>((uint)i);
byte prevI = Memory.Read<byte>((uint)(i - 1));
if (atI == prevI)
{
// for ( j = *(i + 1); j; *currentAddress++ = *i )
for (byte j = Memory.Read<byte>((uint)(i + 1)); j != 0; byteBuffer[currentAddress++] = Memory.Read<byte>((uint)i))
{
j--;
}
// i += 2;
i += 2;
// if ( currentAddres < endAddress )
if (currentAddress < size)
{
// *currentAddress++ = *i;
byteBuffer[currentAddress++] = Memory.Read<byte>((uint)i);
//currentAddress++;
}
}
}
buffer = Marshal.AllocHGlobal(0x2C0);
Marshal.Copy(byteBuffer, 0, buffer, 0x2C0);
}
}
#endregion